diff options
author | Michaël Zasso <targos@protonmail.com> | 2016-05-27 16:37:42 +0200 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2016-06-29 09:04:28 +0200 |
commit | 2cc29517966de7257a2f1b34c58c77225a21e05d (patch) | |
tree | 210bd177df2f06eec16e1e22edafdbcbffe66f8a /deps/v8/src/ppc | |
parent | bbf3838c70aaec1dd296fa75ae334fd1c7866df3 (diff) | |
download | android-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.h | 16 | ||||
-rw-r--r-- | deps/v8/src/ppc/assembler-ppc.cc | 13 | ||||
-rw-r--r-- | deps/v8/src/ppc/assembler-ppc.h | 21 | ||||
-rw-r--r-- | deps/v8/src/ppc/builtins-ppc.cc | 160 | ||||
-rw-r--r-- | deps/v8/src/ppc/code-stubs-ppc.cc | 246 | ||||
-rw-r--r-- | deps/v8/src/ppc/codegen-ppc.cc | 10 | ||||
-rw-r--r-- | deps/v8/src/ppc/deoptimizer-ppc.cc | 13 | ||||
-rw-r--r-- | deps/v8/src/ppc/disasm-ppc.cc | 8 | ||||
-rw-r--r-- | deps/v8/src/ppc/frames-ppc.h | 15 | ||||
-rw-r--r-- | deps/v8/src/ppc/interface-descriptors-ppc.cc | 67 | ||||
-rw-r--r-- | deps/v8/src/ppc/macro-assembler-ppc.cc | 383 | ||||
-rw-r--r-- | deps/v8/src/ppc/macro-assembler-ppc.h | 76 | ||||
-rw-r--r-- | deps/v8/src/ppc/simulator-ppc.cc | 72 |
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, ¬_smi); - __ blr(); - __ bind(¬_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(¬_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(¬_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, ¬_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(¬_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(¬_same); - __ LoadSmiLiteral(r3, Smi::FromInt(EQUAL)); - __ IncrementCounter(isolate()->counters()->string_compare_native(), 1, r4, - r5); - __ Ret(); - - __ bind(¬_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); |