summaryrefslogtreecommitdiff
path: root/deps/v8/src/ppc
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2016-05-27 16:37:42 +0200
committerMichaël Zasso <targos@protonmail.com>2016-06-29 09:04:28 +0200
commit2cc29517966de7257a2f1b34c58c77225a21e05d (patch)
tree210bd177df2f06eec16e1e22edafdbcbffe66f8a /deps/v8/src/ppc
parentbbf3838c70aaec1dd296fa75ae334fd1c7866df3 (diff)
downloadandroid-node-v8-2cc29517966de7257a2f1b34c58c77225a21e05d.tar.gz
android-node-v8-2cc29517966de7257a2f1b34c58c77225a21e05d.tar.bz2
android-node-v8-2cc29517966de7257a2f1b34c58c77225a21e05d.zip
deps: update V8 to 5.1.281.69
Pick up the latest branch-head for V8 5.1. This branch brings in improved language support and performance improvements. For full details: http://v8project.blogspot.com/2016/04/v8-release-51.html * Picks up the latest branch head for 5.1 [1] * Edit v8 gitignore to allow trace_event copy * Update V8 DEP trace_event as per deps/v8/DEPS [2] [1] https://chromium.googlesource.com/v8/v8.git/+/dc81244 [2] https://chromium.googlesource.com/chromium/src/base/trace_event/common/+/c8c8665 PR-URL: https://github.com/nodejs/node/pull/7016 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps/v8/src/ppc')
-rw-r--r--deps/v8/src/ppc/assembler-ppc-inl.h16
-rw-r--r--deps/v8/src/ppc/assembler-ppc.cc13
-rw-r--r--deps/v8/src/ppc/assembler-ppc.h21
-rw-r--r--deps/v8/src/ppc/builtins-ppc.cc160
-rw-r--r--deps/v8/src/ppc/code-stubs-ppc.cc246
-rw-r--r--deps/v8/src/ppc/codegen-ppc.cc10
-rw-r--r--deps/v8/src/ppc/deoptimizer-ppc.cc13
-rw-r--r--deps/v8/src/ppc/disasm-ppc.cc8
-rw-r--r--deps/v8/src/ppc/frames-ppc.h15
-rw-r--r--deps/v8/src/ppc/interface-descriptors-ppc.cc67
-rw-r--r--deps/v8/src/ppc/macro-assembler-ppc.cc383
-rw-r--r--deps/v8/src/ppc/macro-assembler-ppc.h76
-rw-r--r--deps/v8/src/ppc/simulator-ppc.cc72
13 files changed, 644 insertions, 456 deletions
diff --git a/deps/v8/src/ppc/assembler-ppc-inl.h b/deps/v8/src/ppc/assembler-ppc-inl.h
index 42e220809f..c495fee182 100644
--- a/deps/v8/src/ppc/assembler-ppc-inl.h
+++ b/deps/v8/src/ppc/assembler-ppc-inl.h
@@ -89,6 +89,10 @@ Address RelocInfo::target_address() {
return Assembler::target_address_at(pc_, host_);
}
+Address RelocInfo::wasm_memory_reference() {
+ DCHECK(IsWasmMemoryReference(rmode_));
+ return Assembler::target_address_at(pc_, host_);
+}
Address RelocInfo::target_address_address() {
DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) ||
@@ -179,6 +183,18 @@ Address Assembler::return_address_from_call_start(Address pc) {
return pc + (len + 2) * kInstrSize;
}
+void RelocInfo::update_wasm_memory_reference(
+ Address old_base, Address new_base, size_t old_size, size_t new_size,
+ ICacheFlushMode icache_flush_mode) {
+ DCHECK(IsWasmMemoryReference(rmode_));
+ DCHECK(old_base <= wasm_memory_reference() &&
+ wasm_memory_reference() < old_base + old_size);
+ Address updated_reference = new_base + (wasm_memory_reference() - old_base);
+ DCHECK(new_base <= updated_reference &&
+ updated_reference < new_base + new_size);
+ Assembler::set_target_address_at(isolate_, pc_, host_, updated_reference,
+ icache_flush_mode);
+}
Object* RelocInfo::target_object() {
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
diff --git a/deps/v8/src/ppc/assembler-ppc.cc b/deps/v8/src/ppc/assembler-ppc.cc
index aed149bcab..507eec11af 100644
--- a/deps/v8/src/ppc/assembler-ppc.cc
+++ b/deps/v8/src/ppc/assembler-ppc.cc
@@ -849,6 +849,10 @@ void Assembler::addc(Register dst, Register src1, Register src2, OEBit o,
xo_form(EXT2 | ADDCX, dst, src1, src2, o, r);
}
+void Assembler::adde(Register dst, Register src1, Register src2, OEBit o,
+ RCBit r) {
+ xo_form(EXT2 | ADDEX, dst, src1, src2, o, r);
+}
void Assembler::addze(Register dst, Register src1, OEBit o, RCBit r) {
// a special xo_form
@@ -861,12 +865,15 @@ void Assembler::sub(Register dst, Register src1, Register src2, OEBit o,
xo_form(EXT2 | SUBFX, dst, src2, src1, o, r);
}
-
-void Assembler::subfc(Register dst, Register src1, Register src2, OEBit o,
- RCBit r) {
+void Assembler::subc(Register dst, Register src1, Register src2, OEBit o,
+ RCBit r) {
xo_form(EXT2 | SUBFCX, dst, src2, src1, o, r);
}
+void Assembler::sube(Register dst, Register src1, Register src2, OEBit o,
+ RCBit r) {
+ xo_form(EXT2 | SUBFEX, dst, src2, src1, o, r);
+}
void Assembler::subfic(Register dst, Register src, const Operand& imm) {
d_form(SUBFIC, dst, src, imm.imm_, true);
diff --git a/deps/v8/src/ppc/assembler-ppc.h b/deps/v8/src/ppc/assembler-ppc.h
index 58c6c94dc6..3e8be7d75a 100644
--- a/deps/v8/src/ppc/assembler-ppc.h
+++ b/deps/v8/src/ppc/assembler-ppc.h
@@ -808,18 +808,21 @@ class Assembler : public AssemblerBase {
void sub(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
RCBit r = LeaveRC);
- void subfic(Register dst, Register src, const Operand& imm);
+ void subc(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
+ RCBit r = LeaveRC);
+ void sube(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
+ RCBit r = LeaveRC);
- void subfc(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
- RCBit r = LeaveRC);
+ void subfic(Register dst, Register src, const Operand& imm);
void add(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
RCBit r = LeaveRC);
void addc(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
RCBit r = LeaveRC);
-
- void addze(Register dst, Register src1, OEBit o, RCBit r);
+ void adde(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
+ RCBit r = LeaveRC);
+ void addze(Register dst, Register src1, OEBit o = LeaveOE, RCBit r = LeaveRC);
void mullw(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
RCBit r = LeaveRC);
@@ -1216,7 +1219,9 @@ class Assembler : public AssemblerBase {
void dq(uint64_t data);
void dp(uintptr_t data);
- PositionsRecorder* positions_recorder() { return &positions_recorder_; }
+ AssemblerPositionsRecorder* positions_recorder() {
+ return &positions_recorder_;
+ }
// Read/patch instructions
Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
@@ -1463,8 +1468,8 @@ class Assembler : public AssemblerBase {
friend class RelocInfo;
friend class CodePatcher;
friend class BlockTrampolinePoolScope;
- PositionsRecorder positions_recorder_;
- friend class PositionsRecorder;
+ AssemblerPositionsRecorder positions_recorder_;
+ friend class AssemblerPositionsRecorder;
friend class EnsureSpace;
};
diff --git a/deps/v8/src/ppc/builtins-ppc.cc b/deps/v8/src/ppc/builtins-ppc.cc
index f0b76ccc39..884afedb21 100644
--- a/deps/v8/src/ppc/builtins-ppc.cc
+++ b/deps/v8/src/ppc/builtins-ppc.cc
@@ -532,6 +532,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// -- r4 : constructor function
// -- r5 : allocation site or undefined
// -- r6 : new target
+ // -- cp : context
// -- lr : return address
// -- sp[...]: constructor arguments
// -----------------------------------
@@ -547,11 +548,11 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
if (!create_implicit_receiver) {
__ SmiTag(r7, r3, SetRC);
- __ Push(r5, r7);
+ __ Push(cp, r5, r7);
__ PushRoot(Heap::kTheHoleValueRootIndex);
} else {
__ SmiTag(r3);
- __ Push(r5, r3);
+ __ Push(cp, r5, r3);
// Allocate the new receiver object.
__ Push(r4, r6);
@@ -623,7 +624,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// r3: result
// sp[0]: receiver
// sp[1]: number of arguments (smi-tagged)
- __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+ __ LoadP(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
if (create_implicit_receiver) {
// If the result is an object (in the ECMA sense), we should get rid
@@ -754,9 +755,6 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
// r0,r8-r9, cp may be clobbered
ProfileEntryHookStub::MaybeCallEntryHook(masm);
- // Clear the context before we push it when entering the internal frame.
- __ li(cp, Operand::Zero());
-
// Enter an internal frame.
{
FrameScope scope(masm, StackFrame::INTERNAL);
@@ -853,8 +851,7 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
// MANUAL indicates that the scope shouldn't actually generate code to set up
// the frame (that is done below).
FrameScope frame_scope(masm, StackFrame::MANUAL);
- __ PushFixedFrame(r4);
- __ addi(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
+ __ PushStandardFrame(r4);
// Get the bytecode array from the function object and load the pointer to the
// first entry into kInterpreterBytecodeRegister.
@@ -1208,8 +1205,7 @@ void Builtins::Generate_MarkCodeAsExecutedOnce(MacroAssembler* masm) {
__ mr(ip, r3);
// Perform prologue operations usually performed by the young code stub.
- __ PushFixedFrame(r4);
- __ addi(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
+ __ PushStandardFrame(r4);
// Jump to point after the code-age stub.
__ addi(r3, ip, Operand(kNoCodeAgeSequenceLength));
@@ -1454,24 +1450,6 @@ void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
}
-void Builtins::Generate_OsrAfterStackCheck(MacroAssembler* masm) {
- // We check the stack limit as indicator that recompilation might be done.
- Label ok;
- __ LoadRoot(ip, Heap::kStackLimitRootIndex);
- __ cmpl(sp, ip);
- __ bge(&ok);
- {
- FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
- __ CallRuntime(Runtime::kStackGuard);
- }
- __ Jump(masm->isolate()->builtins()->OnStackReplacement(),
- RelocInfo::CODE_TARGET);
-
- __ bind(&ok);
- __ Ret();
-}
-
-
// static
void Builtins::Generate_DatePrototype_GetField(MacroAssembler* masm,
int field_index) {
@@ -1518,6 +1496,27 @@ void Builtins::Generate_DatePrototype_GetField(MacroAssembler* masm,
__ TailCallRuntime(Runtime::kThrowNotDateError);
}
+// static
+void Builtins::Generate_FunctionHasInstance(MacroAssembler* masm) {
+ // ----------- S t a t e -------------
+ // -- r3 : argc
+ // -- sp[0] : first argument (left-hand side)
+ // -- sp[4] : receiver (right-hand side)
+ // -----------------------------------
+
+ {
+ FrameScope scope(masm, StackFrame::INTERNAL);
+ __ LoadP(InstanceOfDescriptor::LeftRegister(),
+ MemOperand(fp, 2 * kPointerSize)); // Load left-hand side.
+ __ LoadP(InstanceOfDescriptor::RightRegister(),
+ MemOperand(fp, 3 * kPointerSize)); // Load right-hand side.
+ InstanceOfStub stub(masm->isolate(), true);
+ __ CallStub(&stub);
+ }
+
+ // Pop the argument and the receiver.
+ __ Ret(2);
+}
// static
void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) {
@@ -1988,19 +1987,21 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
Comment cmnt(masm, "[ PrepareForTailCall");
- // Prepare for tail call only if the debugger is not active.
+ // Prepare for tail call only if ES2015 tail call elimination is enabled.
Label done;
- ExternalReference debug_is_active =
- ExternalReference::debug_is_active_address(masm->isolate());
- __ mov(scratch1, Operand(debug_is_active));
+ ExternalReference is_tail_call_elimination_enabled =
+ ExternalReference::is_tail_call_elimination_enabled_address(
+ masm->isolate());
+ __ mov(scratch1, Operand(is_tail_call_elimination_enabled));
__ lbz(scratch1, MemOperand(scratch1));
__ cmpi(scratch1, Operand::Zero());
- __ bne(&done);
+ __ beq(&done);
// Drop possible interpreter handler/stub frame.
{
Label no_interpreter_frame;
- __ LoadP(scratch3, MemOperand(fp, StandardFrameConstants::kMarkerOffset));
+ __ LoadP(scratch3,
+ MemOperand(fp, CommonFrameConstants::kContextOrFrameTypeOffset));
__ CmpSmiLiteral(scratch3, Smi::FromInt(StackFrame::STUB), r0);
__ bne(&no_interpreter_frame);
__ LoadP(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
@@ -2008,75 +2009,41 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
}
// Check if next frame is an arguments adaptor frame.
+ Register caller_args_count_reg = scratch1;
Label no_arguments_adaptor, formal_parameter_count_loaded;
__ LoadP(scratch2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
- __ LoadP(scratch3,
- MemOperand(scratch2, StandardFrameConstants::kContextOffset));
+ __ LoadP(
+ scratch3,
+ MemOperand(scratch2, CommonFrameConstants::kContextOrFrameTypeOffset));
__ CmpSmiLiteral(scratch3, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
__ bne(&no_arguments_adaptor);
- // Drop arguments adaptor frame and load arguments count.
+ // Drop current frame and load arguments count from arguments adaptor frame.
__ mr(fp, scratch2);
- __ LoadP(scratch1,
+ __ LoadP(caller_args_count_reg,
MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset));
- __ SmiUntag(scratch1);
+ __ SmiUntag(caller_args_count_reg);
__ b(&formal_parameter_count_loaded);
__ bind(&no_arguments_adaptor);
// Load caller's formal parameter count
- __ LoadP(scratch1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+ __ LoadP(scratch1,
+ MemOperand(fp, ArgumentsAdaptorFrameConstants::kFunctionOffset));
__ LoadP(scratch1,
FieldMemOperand(scratch1, JSFunction::kSharedFunctionInfoOffset));
__ LoadWordArith(
- scratch1, FieldMemOperand(
- scratch1, SharedFunctionInfo::kFormalParameterCountOffset));
+ caller_args_count_reg,
+ FieldMemOperand(scratch1,
+ SharedFunctionInfo::kFormalParameterCountOffset));
#if !V8_TARGET_ARCH_PPC64
- __ SmiUntag(scratch1);
+ __ SmiUntag(caller_args_count_reg);
#endif
__ bind(&formal_parameter_count_loaded);
- // Calculate the end of destination area where we will put the arguments
- // after we drop current frame. We add kPointerSize to count the receiver
- // argument which is not included into formal parameters count.
- Register dst_reg = scratch2;
- __ ShiftLeftImm(dst_reg, scratch1, Operand(kPointerSizeLog2));
- __ add(dst_reg, fp, dst_reg);
- __ addi(dst_reg, dst_reg,
- Operand(StandardFrameConstants::kCallerSPOffset + kPointerSize));
-
- Register src_reg = scratch1;
- __ ShiftLeftImm(src_reg, args_reg, Operand(kPointerSizeLog2));
- __ add(src_reg, sp, src_reg);
- // Count receiver argument as well (not included in args_reg).
- __ addi(src_reg, src_reg, Operand(kPointerSize));
-
- if (FLAG_debug_code) {
- __ cmpl(src_reg, dst_reg);
- __ Check(lt, kStackAccessBelowStackPointer);
- }
-
- // Restore caller's frame pointer and return address now as they will be
- // overwritten by the copying loop.
- __ RestoreFrameStateForTailCall();
-
- // Now copy callee arguments to the caller frame going backwards to avoid
- // callee arguments corruption (source and destination areas could overlap).
-
- // Both src_reg and dst_reg are pointing to the word after the one to copy,
- // so they must be pre-decremented in the loop.
- Register tmp_reg = scratch3;
- Label loop;
- __ addi(tmp_reg, args_reg, Operand(1)); // +1 for receiver
- __ mtctr(tmp_reg);
- __ bind(&loop);
- __ LoadPU(tmp_reg, MemOperand(src_reg, -kPointerSize));
- __ StorePU(tmp_reg, MemOperand(dst_reg, -kPointerSize));
- __ bdnz(&loop);
-
- // Leave current frame.
- __ mr(sp, dst_reg);
-
+ ParameterCount callee_args_count(args_reg);
+ __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
+ scratch3);
__ bind(&done);
}
} // namespace
@@ -2551,31 +2518,6 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
{ // Too few parameters: Actual < expected
__ bind(&too_few);
- // If the function is strong we need to throw an error.
- Label no_strong_error;
- __ LoadP(r7, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
- __ lwz(r8, FieldMemOperand(r7, SharedFunctionInfo::kCompilerHintsOffset));
- __ TestBit(r8, SharedFunctionInfo::kStrongModeBit, r0);
- __ beq(&no_strong_error, cr0);
-
- // What we really care about is the required number of arguments.
- __ lwz(r7, FieldMemOperand(r7, SharedFunctionInfo::kLengthOffset));
-#if V8_TARGET_ARCH_PPC64
- // See commment near kLenghtOffset in src/objects.h
- __ srawi(r7, r7, kSmiTagSize);
-#else
- __ SmiUntag(r7);
-#endif
- __ cmp(r3, r7);
- __ bge(&no_strong_error);
-
- {
- FrameScope frame(masm, StackFrame::MANUAL);
- EnterArgumentsAdaptorFrame(masm);
- __ CallRuntime(Runtime::kThrowStrongModeTooFewArguments);
- }
-
- __ bind(&no_strong_error);
EnterArgumentsAdaptorFrame(masm);
ArgumentAdaptorStackCheck(masm, &stack_overflow);
diff --git a/deps/v8/src/ppc/code-stubs-ppc.cc b/deps/v8/src/ppc/code-stubs-ppc.cc
index 03c73af503..0671f990e8 100644
--- a/deps/v8/src/ppc/code-stubs-ppc.cc
+++ b/deps/v8/src/ppc/code-stubs-ppc.cc
@@ -4,9 +4,10 @@
#if V8_TARGET_ARCH_PPC
+#include "src/code-stubs.h"
+#include "src/api-arguments.h"
#include "src/base/bits.h"
#include "src/bootstrapper.h"
-#include "src/code-stubs.h"
#include "src/codegen.h"
#include "src/ic/handler-compiler.h"
#include "src/ic/ic.h"
@@ -76,6 +77,10 @@ void InternalArrayNoArgumentConstructorStub::InitializeDescriptor(
InitializeInternalArrayConstructorDescriptor(isolate(), descriptor, 0);
}
+void FastArrayPushStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
+ Address deopt_handler = Runtime::FunctionForId(Runtime::kArrayPush)->entry;
+ descriptor->Initialize(r3, deopt_handler, -1, JS_FUNCTION_STUB_MODE);
+}
void InternalArraySingleArgumentConstructorStub::InitializeDescriptor(
CodeStubDescriptor* descriptor) {
@@ -494,8 +499,9 @@ static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm, Register lhs,
__ b(both_loaded_as_doubles);
}
-
-// Fast negative check for internalized-to-internalized equality.
+// Fast negative check for internalized-to-internalized equality or receiver
+// equality. Also handles the undetectable receiver to null/undefined
+// comparison.
static void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm,
Register lhs, Register rhs,
Label* possible_strings,
@@ -503,7 +509,7 @@ static void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm,
DCHECK((lhs.is(r3) && rhs.is(r4)) || (lhs.is(r4) && rhs.is(r3)));
// r5 is object type of rhs.
- Label object_test, return_unequal, undetectable;
+ Label object_test, return_equal, return_unequal, undetectable;
STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
__ andi(r0, r5, Operand(kIsNotStringMask));
__ bne(&object_test, cr0);
@@ -541,6 +547,16 @@ static void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm,
__ bind(&undetectable);
__ andi(r0, r8, Operand(1 << Map::kIsUndetectable));
__ beq(&return_unequal, cr0);
+
+ // If both sides are JSReceivers, then the result is false according to
+ // the HTML specification, which says that only comparisons with null or
+ // undefined are affected by special casing for document.all.
+ __ CompareInstanceType(r5, r5, ODDBALL_TYPE);
+ __ beq(&return_equal);
+ __ CompareInstanceType(r6, r6, ODDBALL_TYPE);
+ __ bne(&return_unequal);
+
+ __ bind(&return_equal);
__ li(r3, Operand(EQUAL));
__ Ret();
}
@@ -1409,8 +1425,12 @@ void InstanceOfStub::Generate(MacroAssembler* masm) {
__ CompareObjectType(function, function_map, scratch, JS_FUNCTION_TYPE);
__ bne(&slow_case);
- // Ensure that {function} has an instance prototype.
+ // Go to the runtime if the function is not a constructor.
__ lbz(scratch, FieldMemOperand(function_map, Map::kBitFieldOffset));
+ __ TestBit(scratch, Map::kIsConstructor, r0);
+ __ beq(&slow_case, cr0);
+
+ // Ensure that {function} has an instance prototype.
__ TestBit(scratch, Map::kHasNonInstancePrototype, r0);
__ bne(&slow_case, cr0);
@@ -1478,7 +1498,8 @@ void InstanceOfStub::Generate(MacroAssembler* masm) {
// Slow-case: Call the %InstanceOf runtime function.
__ bind(&slow_case);
__ Push(object, function);
- __ TailCallRuntime(Runtime::kInstanceOf);
+ __ TailCallRuntime(is_es6_instanceof() ? Runtime::kOrdinaryHasInstance
+ : Runtime::kInstanceOf);
}
@@ -1531,29 +1552,6 @@ void LoadIndexedStringStub::Generate(MacroAssembler* masm) {
}
-void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) {
- // Return address is in lr.
- Label slow;
-
- Register receiver = LoadDescriptor::ReceiverRegister();
- Register key = LoadDescriptor::NameRegister();
-
- // Check that the key is an array index, that is Uint32.
- __ TestIfPositiveSmi(key, r0);
- __ bne(&slow, cr0);
-
- // Everything is fine, call runtime.
- __ Push(receiver, key); // Receiver, key.
-
- // Perform tail call to the entry.
- __ TailCallRuntime(Runtime::kLoadElementWithInterceptor);
-
- __ bind(&slow);
- PropertyAccessCompiler::TailCallBuiltin(
- masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
-}
-
-
void RegExpExecStub::Generate(MacroAssembler* masm) {
// Just jump directly to runtime if native RegExp is not selected at compile
// time or if regexp entry in generated code is turned off runtime switch or
@@ -2695,29 +2693,28 @@ void SubStringStub::Generate(MacroAssembler* masm) {
void ToNumberStub::Generate(MacroAssembler* masm) {
// The ToNumber stub takes one argument in r3.
- Label not_smi;
- __ JumpIfNotSmi(r3, &not_smi);
- __ blr();
- __ bind(&not_smi);
+ STATIC_ASSERT(kSmiTag == 0);
+ __ TestIfSmi(r3, r0);
+ __ Ret(eq, cr0);
__ CompareObjectType(r3, r4, r4, HEAP_NUMBER_TYPE);
// r3: receiver
// r4: receiver instance type
__ Ret(eq);
- Label not_string, slow_string;
- __ cmpli(r4, Operand(FIRST_NONSTRING_TYPE));
- __ bge(&not_string);
- // Check if string has a cached array index.
- __ lwz(r5, FieldMemOperand(r3, String::kHashFieldOffset));
- __ And(r0, r5, Operand(String::kContainsCachedArrayIndexMask), SetRC);
- __ bne(&slow_string, cr0);
- __ IndexFromHash(r5, r3);
- __ blr();
- __ bind(&slow_string);
- __ push(r3); // Push argument.
- __ TailCallRuntime(Runtime::kStringToNumber);
- __ bind(&not_string);
+ NonNumberToNumberStub stub(masm->isolate());
+ __ TailCallStub(&stub);
+}
+
+void NonNumberToNumberStub::Generate(MacroAssembler* masm) {
+ // The NonNumberToNumber stub takes one argument in r3.
+ __ AssertNotNumber(r3);
+
+ __ CompareObjectType(r3, r4, r4, FIRST_NONSTRING_TYPE);
+ // r3: receiver
+ // r4: receiver instance type
+ StringToNumberStub stub(masm->isolate());
+ __ TailCallStub(&stub, lt);
Label not_oddball;
__ cmpi(r4, Operand(ODDBALL_TYPE));
@@ -2730,29 +2727,23 @@ void ToNumberStub::Generate(MacroAssembler* masm) {
__ TailCallRuntime(Runtime::kToNumber);
}
+void StringToNumberStub::Generate(MacroAssembler* masm) {
+ // The StringToNumber stub takes one argument in r3.
+ __ AssertString(r3);
-void ToLengthStub::Generate(MacroAssembler* masm) {
- // The ToLength stub takes one argument in r3.
- Label not_smi;
- __ JumpIfNotSmi(r3, &not_smi);
- STATIC_ASSERT(kSmiTag == 0);
- __ cmpi(r3, Operand::Zero());
- if (CpuFeatures::IsSupported(ISELECT)) {
- __ isel(lt, r3, r0, r3);
- } else {
- Label positive;
- __ bgt(&positive);
- __ li(r3, Operand::Zero());
- __ bind(&positive);
- }
- __ Ret();
- __ bind(&not_smi);
+ // Check if string has a cached array index.
+ Label runtime;
+ __ lwz(r5, FieldMemOperand(r3, String::kHashFieldOffset));
+ __ And(r0, r5, Operand(String::kContainsCachedArrayIndexMask), SetRC);
+ __ bne(&runtime, cr0);
+ __ IndexFromHash(r5, r3);
+ __ blr();
+ __ bind(&runtime);
__ push(r3); // Push argument.
- __ TailCallRuntime(Runtime::kToLength);
+ __ TailCallRuntime(Runtime::kStringToNumber);
}
-
void ToStringStub::Generate(MacroAssembler* masm) {
// The ToString stub takes one argument in r3.
Label is_number;
@@ -2933,42 +2924,6 @@ void StringHelper::GenerateOneByteCharsCompareLoop(
}
-void StringCompareStub::Generate(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- r4 : left
- // -- r3 : right
- // -- lr : return address
- // -----------------------------------
- __ AssertString(r4);
- __ AssertString(r3);
-
- Label not_same;
- __ cmp(r3, r4);
- __ bne(&not_same);
- __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL));
- __ IncrementCounter(isolate()->counters()->string_compare_native(), 1, r4,
- r5);
- __ Ret();
-
- __ bind(&not_same);
-
- // Check that both objects are sequential one-byte strings.
- Label runtime;
- __ JumpIfNotBothSequentialOneByteStrings(r4, r3, r5, r6, &runtime);
-
- // Compare flat one-byte strings natively.
- __ IncrementCounter(isolate()->counters()->string_compare_native(), 1, r5,
- r6);
- StringHelper::GenerateCompareFlatOneByteStrings(masm, r4, r3, r5, r6, r7);
-
- // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
- // tagged as a small integer.
- __ bind(&runtime);
- __ Push(r4, r3);
- __ TailCallRuntime(Runtime::kStringCompare);
-}
-
-
void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r4 : left
@@ -3285,10 +3240,17 @@ void CompareICStub::GenerateStrings(MacroAssembler* masm) {
// Handle more complex cases in runtime.
__ bind(&runtime);
- __ Push(left, right);
if (equality) {
- __ TailCallRuntime(Runtime::kStringEquals);
+ {
+ FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
+ __ Push(left, right);
+ __ CallRuntime(Runtime::kStringEqual);
+ }
+ __ LoadRoot(r4, Heap::kTrueValueRootIndex);
+ __ sub(r3, r3, r4);
+ __ Ret();
} else {
+ __ Push(left, right);
__ TailCallRuntime(Runtime::kStringCompare);
}
@@ -3832,7 +3794,7 @@ void StubFailureTrampolineStub::Generate(MacroAssembler* masm) {
CEntryStub ces(isolate(), 1, kSaveFPRegs);
__ Call(ces.GetCode(), RelocInfo::CODE_TARGET);
int parameter_count_offset =
- StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset;
+ StubFailureTrampolineFrameConstants::kArgumentsLengthOffset;
__ LoadP(r4, MemOperand(fp, parameter_count_offset));
if (function_mode() == JS_FUNCTION_STUB_MODE) {
__ addi(r4, r4, Operand(1));
@@ -4844,7 +4806,7 @@ void FastNewRestParameterStub::Generate(MacroAssembler* masm) {
__ bind(&loop);
__ LoadP(r5, MemOperand(r5, StandardFrameConstants::kCallerFPOffset));
__ bind(&loop_entry);
- __ LoadP(ip, MemOperand(r5, StandardFrameConstants::kMarkerOffset));
+ __ LoadP(ip, MemOperand(r5, StandardFrameConstants::kFunctionOffset));
__ cmp(ip, r4);
__ bne(&loop);
}
@@ -4853,7 +4815,7 @@ void FastNewRestParameterStub::Generate(MacroAssembler* masm) {
// arguments adaptor frame below the function frame).
Label no_rest_parameters;
__ LoadP(r5, MemOperand(r5, StandardFrameConstants::kCallerFPOffset));
- __ LoadP(ip, MemOperand(r5, StandardFrameConstants::kContextOffset));
+ __ LoadP(ip, MemOperand(r5, CommonFrameConstants::kContextOrFrameTypeOffset));
__ CmpSmiLiteral(ip, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
__ bne(&no_rest_parameters);
@@ -4998,7 +4960,7 @@ void FastNewSloppyArgumentsStub::Generate(MacroAssembler* masm) {
// Check if the calling frame is an arguments adaptor frame.
Label adaptor_frame, try_allocate, runtime;
__ LoadP(r7, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
- __ LoadP(r3, MemOperand(r7, StandardFrameConstants::kContextOffset));
+ __ LoadP(r3, MemOperand(r7, CommonFrameConstants::kContextOrFrameTypeOffset));
__ CmpSmiLiteral(r3, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
__ beq(&adaptor_frame);
@@ -5240,7 +5202,7 @@ void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) {
__ bind(&loop);
__ LoadP(r5, MemOperand(r5, StandardFrameConstants::kCallerFPOffset));
__ bind(&loop_entry);
- __ LoadP(ip, MemOperand(r5, StandardFrameConstants::kMarkerOffset));
+ __ LoadP(ip, MemOperand(r5, StandardFrameConstants::kFunctionOffset));
__ cmp(ip, r4);
__ bne(&loop);
}
@@ -5248,7 +5210,7 @@ void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) {
// Check if we have an arguments adaptor frame below the function frame.
Label arguments_adaptor, arguments_done;
__ LoadP(r6, MemOperand(r5, StandardFrameConstants::kCallerFPOffset));
- __ LoadP(ip, MemOperand(r6, StandardFrameConstants::kContextOffset));
+ __ LoadP(ip, MemOperand(r6, CommonFrameConstants::kContextOrFrameTypeOffset));
__ CmpSmiLiteral(ip, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
__ beq(&arguments_adaptor);
{
@@ -5632,16 +5594,12 @@ static void CallApiFunctionAndReturn(MacroAssembler* masm,
__ b(&leave_exit_frame);
}
-static void CallApiFunctionStubHelper(MacroAssembler* masm,
- const ParameterCount& argc,
- bool return_first_arg,
- bool call_data_undefined, bool is_lazy) {
+void CallApiCallbackStub::Generate(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r3 : callee
// -- r7 : call_data
// -- r5 : holder
// -- r4 : api_function_address
- // -- r6 : number of arguments if argc is a register
// -- cp : context
// --
// -- sp[0] : last argument
@@ -5667,11 +5625,9 @@ static void CallApiFunctionStubHelper(MacroAssembler* masm,
STATIC_ASSERT(FCA::kHolderIndex == 0);
STATIC_ASSERT(FCA::kArgsLength == 7);
- DCHECK(argc.is_immediate() || r6.is(argc.reg()));
-
// context save
__ push(context);
- if (!is_lazy) {
+ if (!is_lazy()) {
// load context from callee
__ LoadP(context, FieldMemOperand(callee, JSFunction::kContextOffset));
}
@@ -5683,7 +5639,7 @@ static void CallApiFunctionStubHelper(MacroAssembler* masm,
__ push(call_data);
Register scratch = call_data;
- if (!call_data_undefined) {
+ if (!call_data_undefined()) {
__ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
}
// return value
@@ -5719,28 +5675,15 @@ static void CallApiFunctionStubHelper(MacroAssembler* masm,
__ addi(r3, sp, Operand(kFunctionCallbackInfoOffset));
// FunctionCallbackInfo::implicit_args_
__ StoreP(scratch, MemOperand(r3, 0 * kPointerSize));
- if (argc.is_immediate()) {
- // FunctionCallbackInfo::values_
- __ addi(ip, scratch,
- Operand((FCA::kArgsLength - 1 + argc.immediate()) * kPointerSize));
- __ StoreP(ip, MemOperand(r3, 1 * kPointerSize));
- // FunctionCallbackInfo::length_ = argc
- __ li(ip, Operand(argc.immediate()));
- __ stw(ip, MemOperand(r3, 2 * kPointerSize));
- // FunctionCallbackInfo::is_construct_call_ = 0
- __ li(ip, Operand::Zero());
- __ stw(ip, MemOperand(r3, 2 * kPointerSize + kIntSize));
- } else {
- __ ShiftLeftImm(ip, argc.reg(), Operand(kPointerSizeLog2));
- __ addi(ip, ip, Operand((FCA::kArgsLength - 1) * kPointerSize));
- // FunctionCallbackInfo::values_
- __ add(r0, scratch, ip);
- __ StoreP(r0, MemOperand(r3, 1 * kPointerSize));
- // FunctionCallbackInfo::length_ = argc
- __ stw(argc.reg(), MemOperand(r3, 2 * kPointerSize));
- // FunctionCallbackInfo::is_construct_call_
- __ stw(ip, MemOperand(r3, 2 * kPointerSize + kIntSize));
- }
+ // FunctionCallbackInfo::values_
+ __ addi(ip, scratch, Operand((FCA::kArgsLength - 1 + argc()) * kPointerSize));
+ __ StoreP(ip, MemOperand(r3, 1 * kPointerSize));
+ // FunctionCallbackInfo::length_ = argc
+ __ li(ip, Operand(argc()));
+ __ stw(ip, MemOperand(r3, 2 * kPointerSize));
+ // FunctionCallbackInfo::is_construct_call_ = 0
+ __ li(ip, Operand::Zero());
+ __ stw(ip, MemOperand(r3, 2 * kPointerSize + kIntSize));
ExternalReference thunk_ref =
ExternalReference::invoke_function_callback(masm->isolate());
@@ -5750,7 +5693,7 @@ static void CallApiFunctionStubHelper(MacroAssembler* masm,
fp, (2 + FCA::kContextSaveIndex) * kPointerSize);
// Stores return the first js argument
int return_value_offset = 0;
- if (return_first_arg) {
+ if (is_store()) {
return_value_offset = 2 + FCA::kArgsLength;
} else {
return_value_offset = 2 + FCA::kReturnValueOffset;
@@ -5760,33 +5703,14 @@ static void CallApiFunctionStubHelper(MacroAssembler* masm,
MemOperand is_construct_call_operand =
MemOperand(sp, kFunctionCallbackInfoOffset + 2 * kPointerSize + kIntSize);
MemOperand* stack_space_operand = &is_construct_call_operand;
- if (argc.is_immediate()) {
- stack_space = argc.immediate() + FCA::kArgsLength + 1;
- stack_space_operand = NULL;
- }
+ stack_space = argc() + FCA::kArgsLength + 1;
+ stack_space_operand = NULL;
CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, stack_space,
stack_space_operand, return_value_operand,
&context_restore_operand);
}
-void CallApiFunctionStub::Generate(MacroAssembler* masm) {
- bool call_data_undefined = this->call_data_undefined();
- CallApiFunctionStubHelper(masm, ParameterCount(r6), false,
- call_data_undefined, false);
-}
-
-
-void CallApiAccessorStub::Generate(MacroAssembler* masm) {
- bool is_store = this->is_store();
- int argc = this->argc();
- bool call_data_undefined = this->call_data_undefined();
- bool is_lazy = this->is_lazy();
- CallApiFunctionStubHelper(masm, ParameterCount(argc), is_store,
- call_data_undefined, is_lazy);
-}
-
-
void CallApiGetterStub::Generate(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- sp[0] : name
diff --git a/deps/v8/src/ppc/codegen-ppc.cc b/deps/v8/src/ppc/codegen-ppc.cc
index d6d86b0fcc..5642e91f9d 100644
--- a/deps/v8/src/ppc/codegen-ppc.cc
+++ b/deps/v8/src/ppc/codegen-ppc.cc
@@ -136,7 +136,7 @@ void ElementsTransitionGenerator::GenerateMapChangeElementsTransition(
if (mode == TRACK_ALLOCATION_SITE) {
DCHECK(allocation_memento_found != NULL);
- __ JumpIfJSArrayHasAllocationMemento(receiver, scratch_elements,
+ __ JumpIfJSArrayHasAllocationMemento(receiver, scratch_elements, r11,
allocation_memento_found);
}
@@ -169,7 +169,7 @@ void ElementsTransitionGenerator::GenerateSmiToDouble(
scratch2));
if (mode == TRACK_ALLOCATION_SITE) {
- __ JumpIfJSArrayHasAllocationMemento(receiver, elements, fail);
+ __ JumpIfJSArrayHasAllocationMemento(receiver, elements, scratch3, fail);
}
// Check for empty arrays, which only require a map transition and no changes
@@ -289,7 +289,7 @@ void ElementsTransitionGenerator::GenerateDoubleToObject(
scratch));
if (mode == TRACK_ALLOCATION_SITE) {
- __ JumpIfJSArrayHasAllocationMemento(receiver, elements, fail);
+ __ JumpIfJSArrayHasAllocationMemento(receiver, elements, scratch3, fail);
}
// Check for empty arrays, which only require a map transition and no changes
@@ -616,9 +616,7 @@ CodeAgingHelper::CodeAgingHelper(Isolate* isolate) {
young_sequence_.length() / Assembler::kInstrSize,
CodePatcher::DONT_FLUSH));
PredictableCodeSizeScope scope(patcher->masm(), young_sequence_.length());
- patcher->masm()->PushFixedFrame(r4);
- patcher->masm()->addi(fp, sp,
- Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
+ patcher->masm()->PushStandardFrame(r4);
for (int i = 0; i < kNoCodeAgeSequenceNops; i++) {
patcher->masm()->nop();
}
diff --git a/deps/v8/src/ppc/deoptimizer-ppc.cc b/deps/v8/src/ppc/deoptimizer-ppc.cc
index 9ec5cdd11a..ead877e149 100644
--- a/deps/v8/src/ppc/deoptimizer-ppc.cc
+++ b/deps/v8/src/ppc/deoptimizer-ppc.cc
@@ -106,12 +106,6 @@ void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) {
}
}
-bool Deoptimizer::HasAlignmentPadding(SharedFunctionInfo* shared) {
- // There is no dynamic alignment padding on PPC in the input frame.
- return false;
-}
-
-
#define __ masm()->
// This code tries to be close to ia32 code so that any changes can be
@@ -168,7 +162,12 @@ void Deoptimizer::TableEntryGenerator::Generate() {
// Allocate a new deoptimizer object.
// Pass six arguments in r3 to r8.
__ PrepareCallCFunction(6, r8);
+ __ li(r3, Operand::Zero());
+ Label context_check;
+ __ LoadP(r4, MemOperand(fp, CommonFrameConstants::kContextOrFrameTypeOffset));
+ __ JumpIfSmi(r4, &context_check);
__ LoadP(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+ __ bind(&context_check);
__ li(r4, Operand(type())); // bailout type,
// r5: bailout id already loaded.
// r6: code address or 0 already loaded.
@@ -238,6 +237,8 @@ void Deoptimizer::TableEntryGenerator::Generate() {
}
__ pop(r3); // Restore deoptimizer object (class Deoptimizer).
+ __ LoadP(sp, MemOperand(r3, Deoptimizer::caller_frame_top_offset()));
+
// Replace the current (input) frame with the output frames.
Label outer_push_loop, inner_push_loop, outer_loop_header, inner_loop_header;
// Outer loop state: r7 = current "FrameDescription** output_",
diff --git a/deps/v8/src/ppc/disasm-ppc.cc b/deps/v8/src/ppc/disasm-ppc.cc
index e72658fba7..baba14643f 100644
--- a/deps/v8/src/ppc/disasm-ppc.cc
+++ b/deps/v8/src/ppc/disasm-ppc.cc
@@ -657,10 +657,18 @@ void Decoder::DecodeExt2(Instruction* instr) {
Format(instr, "subfc'. 'rt, 'ra, 'rb");
return;
}
+ case SUBFEX: {
+ Format(instr, "subfe'. 'rt, 'ra, 'rb");
+ return;
+ }
case ADDCX: {
Format(instr, "addc'. 'rt, 'ra, 'rb");
return;
}
+ case ADDEX: {
+ Format(instr, "adde'. 'rt, 'ra, 'rb");
+ return;
+ }
case CNTLZWX: {
Format(instr, "cntlzw'. 'ra, 'rs");
return;
diff --git a/deps/v8/src/ppc/frames-ppc.h b/deps/v8/src/ppc/frames-ppc.h
index b1de9f50ff..fd4abe2e4d 100644
--- a/deps/v8/src/ppc/frames-ppc.h
+++ b/deps/v8/src/ppc/frames-ppc.h
@@ -152,16 +152,11 @@ class EntryFrameConstants : public AllStatic {
-(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize);
};
-
-class ExitFrameConstants : public AllStatic {
+class ExitFrameConstants : public TypedFrameConstants {
public:
- static const int kFrameSize =
- FLAG_enable_embedded_constant_pool ? 3 * kPointerSize : 2 * kPointerSize;
-
- static const int kConstantPoolOffset =
- FLAG_enable_embedded_constant_pool ? -3 * kPointerSize : 0;
- static const int kCodeOffset = -2 * kPointerSize;
- static const int kSPOffset = -1 * kPointerSize;
+ static const int kSPOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
+ static const int kCodeOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
+ DEFINE_TYPED_FRAME_SIZES(2);
// The caller fields are below the frame pointer on the stack.
static const int kCallerFPOffset = 0 * kPointerSize;
@@ -179,7 +174,7 @@ class JavaScriptFrameConstants : public AllStatic {
// FP-relative.
static const int kLocal0Offset = StandardFrameConstants::kExpressionsOffset;
static const int kLastParameterOffset = +2 * kPointerSize;
- static const int kFunctionOffset = StandardFrameConstants::kMarkerOffset;
+ static const int kFunctionOffset = StandardFrameConstants::kFunctionOffset;
// Caller SP-relative.
static const int kParam0Offset = -2 * kPointerSize;
diff --git a/deps/v8/src/ppc/interface-descriptors-ppc.cc b/deps/v8/src/ppc/interface-descriptors-ppc.cc
index 3db7bd5c17..48b6cdcf0c 100644
--- a/deps/v8/src/ppc/interface-descriptors-ppc.cc
+++ b/deps/v8/src/ppc/interface-descriptors-ppc.cc
@@ -106,35 +106,9 @@ void FastNewStrictArgumentsDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
-void ToNumberDescriptor::InitializePlatformSpecific(
- CallInterfaceDescriptorData* data) {
- Register registers[] = {r3};
- data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-
-// static
-const Register ToLengthDescriptor::ReceiverRegister() { return r3; }
-
-
-// static
-const Register ToStringDescriptor::ReceiverRegister() { return r3; }
-
// static
-const Register ToNameDescriptor::ReceiverRegister() { return r3; }
-
-
-// static
-const Register ToObjectDescriptor::ReceiverRegister() { return r3; }
-
-
-void NumberToStringDescriptor::InitializePlatformSpecific(
- CallInterfaceDescriptorData* data) {
- Register registers[] = {r3};
- data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
+const Register TypeConversionDescriptor::ArgumentRegister() { return r3; }
void TypeofDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
@@ -262,6 +236,13 @@ void AllocateHeapNumberDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(0, nullptr, nullptr);
}
+#define SIMD128_ALLOC_DESC(TYPE, Type, type, lane_count, lane_type) \
+ void Allocate##Type##Descriptor::InitializePlatformSpecific( \
+ CallInterfaceDescriptorData* data) { \
+ data->InitializePlatformSpecific(0, nullptr, nullptr); \
+ }
+SIMD128_TYPES(SIMD128_ALLOC_DESC)
+#undef SIMD128_ALLOC_DESC
void AllocateInNewSpaceDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
@@ -306,24 +287,16 @@ void InternalArrayConstructorDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
-
-void CompareDescriptor::InitializePlatformSpecific(
- CallInterfaceDescriptorData* data) {
- Register registers[] = {r4, r3};
- data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-
-void CompareNilDescriptor::InitializePlatformSpecific(
+void FastArrayPushDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
+ // stack param count needs (arg count)
Register registers[] = {r3};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
-
-void ToBooleanDescriptor::InitializePlatformSpecific(
+void CompareDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
- Register registers[] = {r3};
+ Register registers[] = {r4, r3};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
@@ -387,21 +360,7 @@ void ArgumentAdaptorDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
-
-void ApiFunctionDescriptor::InitializePlatformSpecific(
- CallInterfaceDescriptorData* data) {
- Register registers[] = {
- r3, // callee
- r7, // call_data
- r5, // holder
- r4, // api_function_address
- r6, // actual number of arguments
- };
- data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
-
-void ApiAccessorDescriptor::InitializePlatformSpecific(
+void ApiCallbackDescriptorBase::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
r3, // callee
diff --git a/deps/v8/src/ppc/macro-assembler-ppc.cc b/deps/v8/src/ppc/macro-assembler-ppc.cc
index 14759de0da..42e5a13157 100644
--- a/deps/v8/src/ppc/macro-assembler-ppc.cc
+++ b/deps/v8/src/ppc/macro-assembler-ppc.cc
@@ -570,14 +570,13 @@ void MacroAssembler::RememberedSetHelper(Register object, // For debug tests.
StoreP(scratch, MemOperand(ip));
// Call stub on end of buffer.
// Check for end of buffer.
- mov(r0, Operand(StoreBuffer::kStoreBufferOverflowBit));
- and_(r0, scratch, r0, SetRC);
+ TestBitMask(scratch, StoreBuffer::kStoreBufferMask, r0);
if (and_then == kFallThroughAtEnd) {
- beq(&done, cr0);
+ bne(&done, cr0);
} else {
DCHECK(and_then == kReturnAtEnd);
- Ret(eq, cr0);
+ Ret(ne, cr0);
}
mflr(r0);
push(r0);
@@ -591,42 +590,69 @@ void MacroAssembler::RememberedSetHelper(Register object, // For debug tests.
}
}
-
-void MacroAssembler::PushFixedFrame(Register marker_reg) {
+void MacroAssembler::PushCommonFrame(Register marker_reg) {
+ int fp_delta = 0;
mflr(r0);
if (FLAG_enable_embedded_constant_pool) {
if (marker_reg.is_valid()) {
- Push(r0, fp, kConstantPoolRegister, cp, marker_reg);
+ Push(r0, fp, kConstantPoolRegister, marker_reg);
+ fp_delta = 2;
} else {
- Push(r0, fp, kConstantPoolRegister, cp);
+ Push(r0, fp, kConstantPoolRegister);
+ fp_delta = 1;
}
} else {
if (marker_reg.is_valid()) {
- Push(r0, fp, cp, marker_reg);
+ Push(r0, fp, marker_reg);
+ fp_delta = 1;
} else {
- Push(r0, fp, cp);
+ Push(r0, fp);
+ fp_delta = 0;
}
}
+ addi(fp, sp, Operand(fp_delta * kPointerSize));
}
-
-void MacroAssembler::PopFixedFrame(Register marker_reg) {
+void MacroAssembler::PopCommonFrame(Register marker_reg) {
if (FLAG_enable_embedded_constant_pool) {
if (marker_reg.is_valid()) {
- Pop(r0, fp, kConstantPoolRegister, cp, marker_reg);
+ Pop(r0, fp, kConstantPoolRegister, marker_reg);
} else {
- Pop(r0, fp, kConstantPoolRegister, cp);
+ Pop(r0, fp, kConstantPoolRegister);
}
} else {
if (marker_reg.is_valid()) {
- Pop(r0, fp, cp, marker_reg);
+ Pop(r0, fp, marker_reg);
} else {
- Pop(r0, fp, cp);
+ Pop(r0, fp);
}
}
mtlr(r0);
}
+void MacroAssembler::PushStandardFrame(Register function_reg) {
+ int fp_delta = 0;
+ mflr(r0);
+ if (FLAG_enable_embedded_constant_pool) {
+ if (function_reg.is_valid()) {
+ Push(r0, fp, kConstantPoolRegister, cp, function_reg);
+ fp_delta = 3;
+ } else {
+ Push(r0, fp, kConstantPoolRegister, cp);
+ fp_delta = 2;
+ }
+ } else {
+ if (function_reg.is_valid()) {
+ Push(r0, fp, cp, function_reg);
+ fp_delta = 2;
+ } else {
+ Push(r0, fp, cp);
+ fp_delta = 1;
+ }
+ }
+ addi(fp, sp, Operand(fp_delta * kPointerSize));
+}
+
void MacroAssembler::RestoreFrameStateForTailCall() {
if (FLAG_enable_embedded_constant_pool) {
LoadP(kConstantPoolRegister,
@@ -803,6 +829,145 @@ void MacroAssembler::ConvertDoubleToUnsignedInt64(
}
#endif
+#if !V8_TARGET_ARCH_PPC64
+void MacroAssembler::ShiftLeftPair(Register dst_low, Register dst_high,
+ Register src_low, Register src_high,
+ Register scratch, Register shift) {
+ DCHECK(!AreAliased(dst_low, src_high, shift));
+ DCHECK(!AreAliased(dst_high, src_low, shift));
+ Label less_than_32;
+ Label done;
+ cmpi(shift, Operand(32));
+ blt(&less_than_32);
+ // If shift >= 32
+ andi(scratch, shift, Operand(0x1f));
+ slw(dst_high, src_low, scratch);
+ li(dst_low, Operand::Zero());
+ b(&done);
+ bind(&less_than_32);
+ // If shift < 32
+ subfic(scratch, shift, Operand(32));
+ slw(dst_high, src_high, shift);
+ srw(scratch, src_low, scratch);
+ orx(dst_high, dst_high, scratch);
+ slw(dst_low, src_low, shift);
+ bind(&done);
+}
+
+void MacroAssembler::ShiftLeftPair(Register dst_low, Register dst_high,
+ Register src_low, Register src_high,
+ uint32_t shift) {
+ DCHECK(!AreAliased(dst_low, src_high));
+ DCHECK(!AreAliased(dst_high, src_low));
+ if (shift == 32) {
+ Move(dst_high, src_low);
+ li(dst_low, Operand::Zero());
+ } else if (shift > 32) {
+ shift &= 0x1f;
+ slwi(dst_high, src_low, Operand(shift));
+ li(dst_low, Operand::Zero());
+ } else if (shift == 0) {
+ Move(dst_low, src_low);
+ Move(dst_high, src_high);
+ } else {
+ slwi(dst_high, src_high, Operand(shift));
+ rlwimi(dst_high, src_low, shift, 32 - shift, 31);
+ slwi(dst_low, src_low, Operand(shift));
+ }
+}
+
+void MacroAssembler::ShiftRightPair(Register dst_low, Register dst_high,
+ Register src_low, Register src_high,
+ Register scratch, Register shift) {
+ DCHECK(!AreAliased(dst_low, src_high, shift));
+ DCHECK(!AreAliased(dst_high, src_low, shift));
+ Label less_than_32;
+ Label done;
+ cmpi(shift, Operand(32));
+ blt(&less_than_32);
+ // If shift >= 32
+ andi(scratch, shift, Operand(0x1f));
+ srw(dst_low, src_high, scratch);
+ li(dst_high, Operand::Zero());
+ b(&done);
+ bind(&less_than_32);
+ // If shift < 32
+ subfic(scratch, shift, Operand(32));
+ srw(dst_low, src_low, shift);
+ slw(scratch, src_high, scratch);
+ orx(dst_low, dst_low, scratch);
+ srw(dst_high, src_high, shift);
+ bind(&done);
+}
+
+void MacroAssembler::ShiftRightPair(Register dst_low, Register dst_high,
+ Register src_low, Register src_high,
+ uint32_t shift) {
+ DCHECK(!AreAliased(dst_low, src_high));
+ DCHECK(!AreAliased(dst_high, src_low));
+ if (shift == 32) {
+ Move(dst_low, src_high);
+ li(dst_high, Operand::Zero());
+ } else if (shift > 32) {
+ shift &= 0x1f;
+ srwi(dst_low, src_high, Operand(shift));
+ li(dst_high, Operand::Zero());
+ } else if (shift == 0) {
+ Move(dst_low, src_low);
+ Move(dst_high, src_high);
+ } else {
+ srwi(dst_low, src_low, Operand(shift));
+ rlwimi(dst_low, src_high, 32 - shift, 0, shift - 1);
+ srwi(dst_high, src_high, Operand(shift));
+ }
+}
+
+void MacroAssembler::ShiftRightAlgPair(Register dst_low, Register dst_high,
+ Register src_low, Register src_high,
+ Register scratch, Register shift) {
+ DCHECK(!AreAliased(dst_low, src_high, shift));
+ DCHECK(!AreAliased(dst_high, src_low, shift));
+ Label less_than_32;
+ Label done;
+ cmpi(shift, Operand(32));
+ blt(&less_than_32);
+ // If shift >= 32
+ andi(scratch, shift, Operand(0x1f));
+ sraw(dst_low, src_high, scratch);
+ srawi(dst_high, src_high, 31);
+ b(&done);
+ bind(&less_than_32);
+ // If shift < 32
+ subfic(scratch, shift, Operand(32));
+ srw(dst_low, src_low, shift);
+ slw(scratch, src_high, scratch);
+ orx(dst_low, dst_low, scratch);
+ sraw(dst_high, src_high, shift);
+ bind(&done);
+}
+
+void MacroAssembler::ShiftRightAlgPair(Register dst_low, Register dst_high,
+ Register src_low, Register src_high,
+ uint32_t shift) {
+ DCHECK(!AreAliased(dst_low, src_high));
+ DCHECK(!AreAliased(dst_high, src_low));
+ if (shift == 32) {
+ Move(dst_low, src_high);
+ srawi(dst_high, src_high, 31);
+ } else if (shift > 32) {
+ shift &= 0x1f;
+ srawi(dst_low, src_high, shift);
+ srawi(dst_high, src_high, 31);
+ } else if (shift == 0) {
+ Move(dst_low, src_low);
+ Move(dst_high, src_high);
+ } else {
+ srwi(dst_low, src_low, Operand(shift));
+ rlwimi(dst_low, src_high, 32 - shift, 0, shift - 1);
+ srawi(dst_high, src_high, shift);
+ }
+}
+#endif
void MacroAssembler::LoadConstantPoolPointerRegisterFromCodeTargetAddress(
Register code_target_address) {
@@ -824,12 +989,13 @@ void MacroAssembler::LoadConstantPoolPointerRegister() {
mov_label_addr(kConstantPoolRegister, ConstantPoolPosition());
}
-
-void MacroAssembler::StubPrologue(Register base, int prologue_offset) {
- LoadSmiLiteral(r11, Smi::FromInt(StackFrame::STUB));
- PushFixedFrame(r11);
- // Adjust FP to point to saved FP.
- addi(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
+void MacroAssembler::StubPrologue(StackFrame::Type type, Register base,
+ int prologue_offset) {
+ {
+ ConstantPoolUnavailableScope constant_pool_unavailable(this);
+ LoadSmiLiteral(r11, Smi::FromInt(type));
+ PushCommonFrame(r11);
+ }
if (FLAG_enable_embedded_constant_pool) {
if (!base.is(no_reg)) {
// base contains prologue address
@@ -865,9 +1031,7 @@ void MacroAssembler::Prologue(bool code_pre_aging, Register base,
}
} else {
// This matches the code found in GetNoCodeAgeSequence()
- PushFixedFrame(r4);
- // Adjust fp to point to saved fp.
- addi(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
+ PushStandardFrame(r4);
for (int i = 0; i < kNoCodeAgeSequenceNops; i++) {
nop();
}
@@ -892,20 +1056,20 @@ void MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) {
void MacroAssembler::EnterFrame(StackFrame::Type type,
bool load_constant_pool_pointer_reg) {
if (FLAG_enable_embedded_constant_pool && load_constant_pool_pointer_reg) {
- PushFixedFrame();
- // This path should not rely on ip containing code entry.
+ // Push type explicitly so we can leverage the constant pool.
+ // This path cannot rely on ip containing code entry.
+ PushCommonFrame();
LoadConstantPoolPointerRegister();
LoadSmiLiteral(ip, Smi::FromInt(type));
push(ip);
} else {
LoadSmiLiteral(ip, Smi::FromInt(type));
- PushFixedFrame(ip);
+ PushCommonFrame(ip);
+ }
+ if (type == StackFrame::INTERNAL) {
+ mov(r0, Operand(CodeObject()));
+ push(r0);
}
- // Adjust FP to point to saved FP.
- addi(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
-
- mov(r0, Operand(CodeObject()));
- push(r0);
}
@@ -921,11 +1085,8 @@ int MacroAssembler::LeaveFrame(StackFrame::Type type, int stack_adjustment) {
LoadP(r0, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
LoadP(ip, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
if (FLAG_enable_embedded_constant_pool) {
- const int exitOffset = ExitFrameConstants::kConstantPoolOffset;
- const int standardOffset = StandardFrameConstants::kConstantPoolOffset;
- const int offset =
- ((type == StackFrame::EXIT) ? exitOffset : standardOffset);
- LoadP(kConstantPoolRegister, MemOperand(fp, offset));
+ LoadP(kConstantPoolRegister,
+ MemOperand(fp, StandardFrameConstants::kConstantPoolOffset));
}
mtlr(r0);
frame_ends = pc_offset();
@@ -962,12 +1123,10 @@ void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) {
// all of the pushes that have happened inside of V8
// since we were called from C code
- // replicate ARM frame - TODO make this more closely follow PPC ABI
- mflr(r0);
- Push(r0, fp);
- mr(fp, sp);
+ LoadSmiLiteral(ip, Smi::FromInt(StackFrame::EXIT));
+ PushCommonFrame(ip);
// Reserve room for saved entry sp and code object.
- subi(sp, sp, Operand(ExitFrameConstants::kFrameSize));
+ subi(sp, fp, Operand(ExitFrameConstants::kFixedFrameSizeFromFp));
if (emit_debug_code()) {
li(r8, Operand::Zero());
@@ -1052,7 +1211,7 @@ void MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count,
// Calculate the stack location of the saved doubles and restore them.
const int kNumRegs = kNumCallerSavedDoubles;
const int offset =
- (ExitFrameConstants::kFrameSize + kNumRegs * kDoubleSize);
+ (ExitFrameConstants::kFixedFrameSizeFromFp + kNumRegs * kDoubleSize);
addi(r6, fp, Operand(-offset));
MultiPopDoubles(kCallerSavedDoubles, r6);
}
@@ -1093,6 +1252,67 @@ void MacroAssembler::MovFromFloatParameter(const DoubleRegister dst) {
Move(dst, d1);
}
+void MacroAssembler::PrepareForTailCall(const ParameterCount& callee_args_count,
+ Register caller_args_count_reg,
+ Register scratch0, Register scratch1) {
+#if DEBUG
+ if (callee_args_count.is_reg()) {
+ DCHECK(!AreAliased(callee_args_count.reg(), caller_args_count_reg, scratch0,
+ scratch1));
+ } else {
+ DCHECK(!AreAliased(caller_args_count_reg, scratch0, scratch1));
+ }
+#endif
+
+ // Calculate the end of destination area where we will put the arguments
+ // after we drop current frame. We add kPointerSize to count the receiver
+ // argument which is not included into formal parameters count.
+ Register dst_reg = scratch0;
+ ShiftLeftImm(dst_reg, caller_args_count_reg, Operand(kPointerSizeLog2));
+ add(dst_reg, fp, dst_reg);
+ addi(dst_reg, dst_reg,
+ Operand(StandardFrameConstants::kCallerSPOffset + kPointerSize));
+
+ Register src_reg = caller_args_count_reg;
+ // Calculate the end of source area. +kPointerSize is for the receiver.
+ if (callee_args_count.is_reg()) {
+ ShiftLeftImm(src_reg, callee_args_count.reg(), Operand(kPointerSizeLog2));
+ add(src_reg, sp, src_reg);
+ addi(src_reg, src_reg, Operand(kPointerSize));
+ } else {
+ Add(src_reg, sp, (callee_args_count.immediate() + 1) * kPointerSize, r0);
+ }
+
+ if (FLAG_debug_code) {
+ cmpl(src_reg, dst_reg);
+ Check(lt, kStackAccessBelowStackPointer);
+ }
+
+ // Restore caller's frame pointer and return address now as they will be
+ // overwritten by the copying loop.
+ RestoreFrameStateForTailCall();
+
+ // Now copy callee arguments to the caller frame going backwards to avoid
+ // callee arguments corruption (source and destination areas could overlap).
+
+ // Both src_reg and dst_reg are pointing to the word after the one to copy,
+ // so they must be pre-decremented in the loop.
+ Register tmp_reg = scratch1;
+ Label loop;
+ if (callee_args_count.is_reg()) {
+ addi(tmp_reg, callee_args_count.reg(), Operand(1)); // +1 for receiver
+ } else {
+ mov(tmp_reg, Operand(callee_args_count.immediate() + 1));
+ }
+ mtctr(tmp_reg);
+ bind(&loop);
+ LoadPU(tmp_reg, MemOperand(src_reg, -kPointerSize));
+ StorePU(tmp_reg, MemOperand(dst_reg, -kPointerSize));
+ bdnz(&loop);
+
+ // Leave current frame.
+ mr(sp, dst_reg);
+}
void MacroAssembler::InvokePrologue(const ParameterCount& expected,
const ParameterCount& actual, Label* done,
@@ -1370,8 +1590,20 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
DCHECK(!holder_reg.is(ip));
DCHECK(!scratch.is(ip));
- // Load current lexical context from the stack frame.
- LoadP(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset));
+ // Load current lexical context from the active StandardFrame, which
+ // may require crawling past STUB frames.
+ Label load_context;
+ Label has_context;
+ DCHECK(!ip.is(scratch));
+ mr(ip, fp);
+ bind(&load_context);
+ LoadP(scratch,
+ MemOperand(ip, CommonFrameConstants::kContextOrFrameTypeOffset));
+ JumpIfNotSmi(scratch, &has_context);
+ LoadP(ip, MemOperand(ip, CommonFrameConstants::kCallerFPOffset));
+ b(&load_context);
+ bind(&has_context);
+
// In debug mode, make sure the lexical context is set.
#ifdef DEBUG
cmpi(scratch, Operand::Zero());
@@ -2679,6 +2911,17 @@ void MacroAssembler::JumpIfEitherSmi(Register reg1, Register reg2,
JumpIfSmi(reg2, on_either_smi);
}
+void MacroAssembler::AssertNotNumber(Register object) {
+ if (emit_debug_code()) {
+ STATIC_ASSERT(kSmiTag == 0);
+ TestIfSmi(object, r0);
+ Check(ne, kOperandIsANumber, cr0);
+ push(object);
+ CompareObjectType(object, object, object, HEAP_NUMBER_TYPE);
+ pop(object);
+ Check(ne, kOperandIsANumber);
+ }
+}
void MacroAssembler::AssertNotSmi(Register object) {
if (emit_debug_code()) {
@@ -4228,28 +4471,52 @@ void MacroAssembler::StoreDouble(DoubleRegister src, const MemOperand& mem,
}
}
-
void MacroAssembler::TestJSArrayForAllocationMemento(Register receiver_reg,
Register scratch_reg,
+ Register scratch2_reg,
Label* no_memento_found) {
- ExternalReference new_space_start =
- ExternalReference::new_space_start(isolate());
+ Label map_check;
+ Label top_check;
ExternalReference new_space_allocation_top =
ExternalReference::new_space_allocation_top_address(isolate());
- addi(scratch_reg, receiver_reg,
- Operand(JSArray::kSize + AllocationMemento::kSize - kHeapObjectTag));
- Cmpi(scratch_reg, Operand(new_space_start), r0);
- blt(no_memento_found);
- mov(ip, Operand(new_space_allocation_top));
- LoadP(ip, MemOperand(ip));
- cmp(scratch_reg, ip);
+ const int kMementoMapOffset = JSArray::kSize - kHeapObjectTag;
+ const int kMementoEndOffset = kMementoMapOffset + AllocationMemento::kSize;
+ Register mask = scratch2_reg;
+
+ DCHECK(!AreAliased(receiver_reg, scratch_reg, mask));
+
+ // Bail out if the object is not in new space.
+ JumpIfNotInNewSpace(receiver_reg, scratch_reg, no_memento_found);
+
+ DCHECK((~Page::kPageAlignmentMask & 0xffff) == 0);
+ lis(mask, Operand((~Page::kPageAlignmentMask >> 16)));
+ addi(scratch_reg, receiver_reg, Operand(kMementoEndOffset));
+
+ // If the object is in new space, we need to check whether it is on the same
+ // page as the current top.
+ Xor(r0, scratch_reg, Operand(new_space_allocation_top));
+ and_(r0, r0, mask, SetRC);
+ beq(&top_check, cr0);
+ // The object is on a different page than allocation top. Bail out if the
+ // object sits on the page boundary as no memento can follow and we cannot
+ // touch the memory following it.
+ xor_(r0, scratch_reg, receiver_reg);
+ and_(r0, r0, mask, SetRC);
+ bne(no_memento_found, cr0);
+ // Continue with the actual map check.
+ b(&map_check);
+ // If top is on the same page as the current object, we need to check whether
+ // we are below top.
+ bind(&top_check);
+ Cmpi(scratch_reg, Operand(new_space_allocation_top), r0);
bgt(no_memento_found);
- LoadP(scratch_reg, MemOperand(scratch_reg, -AllocationMemento::kSize));
+ // Memento map check.
+ bind(&map_check);
+ LoadP(scratch_reg, MemOperand(receiver_reg, kMementoMapOffset));
Cmpi(scratch_reg, Operand(isolate()->factory()->allocation_memento_map()),
r0);
}
-
Register GetRegisterThatIsNotOneOf(Register reg1, Register reg2, Register reg3,
Register reg4, Register reg5,
Register reg6) {
diff --git a/deps/v8/src/ppc/macro-assembler-ppc.h b/deps/v8/src/ppc/macro-assembler-ppc.h
index d9dbd56827..a529b627f2 100644
--- a/deps/v8/src/ppc/macro-assembler-ppc.h
+++ b/deps/v8/src/ppc/macro-assembler-ppc.h
@@ -156,12 +156,6 @@ class MacroAssembler : public Assembler {
void Call(Label* target);
- // Emit call to the code we are currently generating.
- void CallSelf() {
- Handle<Code> self(reinterpret_cast<Code**>(CodeObject().location()));
- Call(self, RelocInfo::CODE_TARGET);
- }
-
// Register move. May do nothing if the registers are identical.
void Move(Register dst, Smi* smi) { LoadSmiLiteral(dst, smi); }
void Move(Register dst, Handle<Object> value);
@@ -344,10 +338,14 @@ class MacroAssembler : public Assembler {
addi(sp, sp, Operand(5 * kPointerSize));
}
- // Push a fixed frame, consisting of lr, fp, context and
- // JS function / marker id if marker_reg is a valid register.
- void PushFixedFrame(Register marker_reg = no_reg);
- void PopFixedFrame(Register marker_reg = no_reg);
+ // Push a fixed frame, consisting of lr, fp, constant pool.
+ void PushCommonFrame(Register marker_reg = no_reg);
+
+ // Push a standard frame, consisting of lr, fp, constant pool,
+ // context and JS function
+ void PushStandardFrame(Register function_reg);
+
+ void PopCommonFrame(Register marker_reg = no_reg);
// Restore caller's frame pointer and return address prior to being
// overwritten by tail call stack preparation.
@@ -416,8 +414,24 @@ class MacroAssembler : public Assembler {
FPRoundingMode rounding_mode = kRoundToZero);
#endif
+#if !V8_TARGET_ARCH_PPC64
+ void ShiftLeftPair(Register dst_low, Register dst_high, Register src_low,
+ Register src_high, Register scratch, Register shift);
+ void ShiftLeftPair(Register dst_low, Register dst_high, Register src_low,
+ Register src_high, uint32_t shift);
+ void ShiftRightPair(Register dst_low, Register dst_high, Register src_low,
+ Register src_high, Register scratch, Register shift);
+ void ShiftRightPair(Register dst_low, Register dst_high, Register src_low,
+ Register src_high, uint32_t shift);
+ void ShiftRightAlgPair(Register dst_low, Register dst_high, Register src_low,
+ Register src_high, Register scratch, Register shift);
+ void ShiftRightAlgPair(Register dst_low, Register dst_high, Register src_low,
+ Register src_high, uint32_t shift);
+#endif
+
// Generates function and stub prologue code.
- void StubPrologue(Register base = no_reg, int prologue_offset = 0);
+ void StubPrologue(StackFrame::Type type, Register base = no_reg,
+ int prologue_offset = 0);
void Prologue(bool code_pre_aging, Register base, int prologue_offset = 0);
// Enter exit frame.
@@ -564,6 +578,15 @@ class MacroAssembler : public Assembler {
// ---------------------------------------------------------------------------
// JavaScript invokes
+ // Removes current frame and its arguments from the stack preserving
+ // the arguments and a return address pushed to the stack for the next call.
+ // Both |callee_args_count| and |caller_args_count_reg| do not include
+ // receiver. |callee_args_count| is not modified, |caller_args_count_reg|
+ // is trashed.
+ void PrepareForTailCall(const ParameterCount& callee_args_count,
+ Register caller_args_count_reg, Register scratch0,
+ Register scratch1);
+
// Invoke the JavaScript function code by either calling or jumping.
void InvokeFunctionCode(Register function, Register new_target,
const ParameterCount& expected,
@@ -1096,14 +1119,16 @@ class MacroAssembler : public Assembler {
// (for consistency between 32/64-bit).
// Extract consecutive bits (defined by rangeStart - rangeEnd) from src
- // and place them into the least significant bits of dst.
+ // and, if !test, shift them into the least significant bits of dst.
inline void ExtractBitRange(Register dst, Register src, int rangeStart,
- int rangeEnd, RCBit rc = LeaveRC) {
+ int rangeEnd, RCBit rc = LeaveRC,
+ bool test = false) {
DCHECK(rangeStart >= rangeEnd && rangeStart < kBitsPerPointer);
int rotate = (rangeEnd == 0) ? 0 : kBitsPerPointer - rangeEnd;
int width = rangeStart - rangeEnd + 1;
- if (rc == SetRC && rangeEnd == 0 && width <= 16) {
- andi(dst, src, Operand((1 << width) - 1));
+ if (rc == SetRC && rangeStart < 16 && (rangeEnd == 0 || test)) {
+ // Prefer faster andi when applicable.
+ andi(dst, src, Operand(((1 << width) - 1) << rangeEnd));
} else {
#if V8_TARGET_ARCH_PPC64
rldicl(dst, src, rotate, kBitsPerPointer - width, rc);
@@ -1115,14 +1140,14 @@ class MacroAssembler : public Assembler {
}
inline void ExtractBit(Register dst, Register src, uint32_t bitNumber,
- RCBit rc = LeaveRC) {
- ExtractBitRange(dst, src, bitNumber, bitNumber, rc);
+ RCBit rc = LeaveRC, bool test = false) {
+ ExtractBitRange(dst, src, bitNumber, bitNumber, rc, test);
}
// Extract consecutive bits (defined by mask) from src and place them
// into the least significant bits of dst.
inline void ExtractBitMask(Register dst, Register src, uintptr_t mask,
- RCBit rc = LeaveRC) {
+ RCBit rc = LeaveRC, bool test = false) {
int start = kBitsPerPointer - 1;
int end;
uintptr_t bit = (1L << start);
@@ -1142,25 +1167,25 @@ class MacroAssembler : public Assembler {
// 1-bits in mask must be contiguous
DCHECK(bit == 0 || (mask & ((bit << 1) - 1)) == 0);
- ExtractBitRange(dst, src, start, end, rc);
+ ExtractBitRange(dst, src, start, end, rc, test);
}
// Test single bit in value.
inline void TestBit(Register value, int bitNumber, Register scratch = r0) {
- ExtractBitRange(scratch, value, bitNumber, bitNumber, SetRC);
+ ExtractBitRange(scratch, value, bitNumber, bitNumber, SetRC, true);
}
// Test consecutive bit range in value. Range is defined by
// rangeStart - rangeEnd.
inline void TestBitRange(Register value, int rangeStart, int rangeEnd,
Register scratch = r0) {
- ExtractBitRange(scratch, value, rangeStart, rangeEnd, SetRC);
+ ExtractBitRange(scratch, value, rangeStart, rangeEnd, SetRC, true);
}
// Test consecutive bit range in value. Range is defined by mask.
inline void TestBitMask(Register value, uintptr_t mask,
Register scratch = r0) {
- ExtractBitMask(scratch, value, mask, SetRC);
+ ExtractBitMask(scratch, value, mask, SetRC, true);
}
@@ -1307,6 +1332,9 @@ class MacroAssembler : public Assembler {
// Jump if either of the registers contain a smi.
void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi);
+ // Abort execution if argument is a number, enabled via --debug-code.
+ void AssertNotNumber(Register object);
+
// Abort execution if argument is a smi, enabled via --debug-code.
void AssertNotSmi(Register object);
void AssertSmi(Register object);
@@ -1481,13 +1509,15 @@ class MacroAssembler : public Assembler {
// If allocation info is present, condition flags are set to eq.
void TestJSArrayForAllocationMemento(Register receiver_reg,
Register scratch_reg,
+ Register scratch2_reg,
Label* no_memento_found);
void JumpIfJSArrayHasAllocationMemento(Register receiver_reg,
Register scratch_reg,
+ Register scratch2_reg,
Label* memento_found) {
Label no_memento_found;
- TestJSArrayForAllocationMemento(receiver_reg, scratch_reg,
+ TestJSArrayForAllocationMemento(receiver_reg, scratch_reg, scratch2_reg,
&no_memento_found);
beq(memento_found);
bind(&no_memento_found);
diff --git a/deps/v8/src/ppc/simulator-ppc.cc b/deps/v8/src/ppc/simulator-ppc.cc
index 9a1f9e035f..79dc8252b7 100644
--- a/deps/v8/src/ppc/simulator-ppc.cc
+++ b/deps/v8/src/ppc/simulator-ppc.cc
@@ -1733,8 +1733,8 @@ bool Simulator::ExecuteExt2_10bit(Instruction* instr) {
int ra = instr->RAValue();
int rb = instr->RBValue();
uint32_t rs_val = get_register(rs);
- uintptr_t rb_val = get_register(rb);
- intptr_t result = rs_val >> (rb_val & 0x3f);
+ uintptr_t rb_val = get_register(rb) & 0x3f;
+ intptr_t result = (rb_val > 31) ? 0 : rs_val >> rb_val;
set_register(ra, result);
if (instr->Bit(0)) { // RC bit set
SetCR0(result);
@@ -1747,8 +1747,8 @@ bool Simulator::ExecuteExt2_10bit(Instruction* instr) {
int ra = instr->RAValue();
int rb = instr->RBValue();
uintptr_t rs_val = get_register(rs);
- uintptr_t rb_val = get_register(rb);
- intptr_t result = rs_val >> (rb_val & 0x7f);
+ uintptr_t rb_val = get_register(rb) & 0x7f;
+ intptr_t result = (rb_val > 63) ? 0 : rs_val >> rb_val;
set_register(ra, result);
if (instr->Bit(0)) { // RC bit set
SetCR0(result);
@@ -1761,8 +1761,8 @@ bool Simulator::ExecuteExt2_10bit(Instruction* instr) {
int ra = instr->RAValue();
int rb = instr->RBValue();
int32_t rs_val = get_register(rs);
- intptr_t rb_val = get_register(rb);
- intptr_t result = rs_val >> (rb_val & 0x3f);
+ intptr_t rb_val = get_register(rb) & 0x3f;
+ intptr_t result = (rb_val > 31) ? rs_val >> 31 : rs_val >> rb_val;
set_register(ra, result);
if (instr->Bit(0)) { // RC bit set
SetCR0(result);
@@ -1775,8 +1775,8 @@ bool Simulator::ExecuteExt2_10bit(Instruction* instr) {
int ra = instr->RAValue();
int rb = instr->RBValue();
intptr_t rs_val = get_register(rs);
- intptr_t rb_val = get_register(rb);
- intptr_t result = rs_val >> (rb_val & 0x7f);
+ intptr_t rb_val = get_register(rb) & 0x7f;
+ intptr_t result = (rb_val > 63) ? rs_val >> 63 : rs_val >> rb_val;
set_register(ra, result);
if (instr->Bit(0)) { // RC bit set
SetCR0(result);
@@ -2025,19 +2025,37 @@ bool Simulator::ExecuteExt2_9bit_part1(Instruction* instr) {
uintptr_t ra_val = get_register(ra);
uintptr_t rb_val = get_register(rb);
uintptr_t alu_out = ~ra_val + rb_val + 1;
- set_register(rt, alu_out);
- // If the sign of rb and alu_out don't match, carry = 0
- if ((alu_out ^ rb_val) & 0x80000000) {
- special_reg_xer_ &= ~0xF0000000;
- } else {
+ // Set carry
+ if (ra_val <= rb_val) {
special_reg_xer_ = (special_reg_xer_ & ~0xF0000000) | 0x20000000;
+ } else {
+ special_reg_xer_ &= ~0xF0000000;
}
+ set_register(rt, alu_out);
if (instr->Bit(0)) { // RC bit set
SetCR0(alu_out);
}
// todo - handle OE bit
break;
}
+ case SUBFEX: {
+ int rt = instr->RTValue();
+ int ra = instr->RAValue();
+ int rb = instr->RBValue();
+ // int oe = instr->Bit(10);
+ uintptr_t ra_val = get_register(ra);
+ uintptr_t rb_val = get_register(rb);
+ uintptr_t alu_out = ~ra_val + rb_val;
+ if (special_reg_xer_ & 0x20000000) {
+ alu_out += 1;
+ }
+ set_register(rt, alu_out);
+ if (instr->Bit(0)) { // RC bit set
+ SetCR0(static_cast<intptr_t>(alu_out));
+ }
+ // todo - handle OE bit
+ break;
+ }
case ADDCX: {
int rt = instr->RTValue();
int ra = instr->RAValue();
@@ -2046,7 +2064,7 @@ bool Simulator::ExecuteExt2_9bit_part1(Instruction* instr) {
uintptr_t ra_val = get_register(ra);
uintptr_t rb_val = get_register(rb);
uintptr_t alu_out = ra_val + rb_val;
- // Check overflow
+ // Set carry
if (~ra_val < rb_val) {
special_reg_xer_ = (special_reg_xer_ & ~0xF0000000) | 0x20000000;
} else {
@@ -2059,6 +2077,24 @@ bool Simulator::ExecuteExt2_9bit_part1(Instruction* instr) {
// todo - handle OE bit
break;
}
+ case ADDEX: {
+ int rt = instr->RTValue();
+ int ra = instr->RAValue();
+ int rb = instr->RBValue();
+ // int oe = instr->Bit(10);
+ uintptr_t ra_val = get_register(ra);
+ uintptr_t rb_val = get_register(rb);
+ uintptr_t alu_out = ra_val + rb_val;
+ if (special_reg_xer_ & 0x20000000) {
+ alu_out += 1;
+ }
+ set_register(rt, alu_out);
+ if (instr->Bit(0)) { // RC bit set
+ SetCR0(static_cast<intptr_t>(alu_out));
+ }
+ // todo - handle OE bit
+ break;
+ }
case MULHWX: {
int rt = instr->RTValue();
int ra = instr->RAValue();
@@ -2117,8 +2153,8 @@ bool Simulator::ExecuteExt2_9bit_part1(Instruction* instr) {
int ra = instr->RAValue();
int rb = instr->RBValue();
uint32_t rs_val = get_register(rs);
- uintptr_t rb_val = get_register(rb);
- uint32_t result = rs_val << (rb_val & 0x3f);
+ uintptr_t rb_val = get_register(rb) & 0x3f;
+ uint32_t result = (rb_val > 31) ? 0 : rs_val << rb_val;
set_register(ra, result);
if (instr->Bit(0)) { // RC bit set
SetCR0(result);
@@ -2131,8 +2167,8 @@ bool Simulator::ExecuteExt2_9bit_part1(Instruction* instr) {
int ra = instr->RAValue();
int rb = instr->RBValue();
uintptr_t rs_val = get_register(rs);
- uintptr_t rb_val = get_register(rb);
- uintptr_t result = rs_val << (rb_val & 0x7f);
+ uintptr_t rb_val = get_register(rb) & 0x7f;
+ uintptr_t result = (rb_val > 63) ? 0 : rs_val << rb_val;
set_register(ra, result);
if (instr->Bit(0)) { // RC bit set
SetCR0(result);