diff options
Diffstat (limited to 'deps/v8/src/ia32/lithium-codegen-ia32.cc')
-rw-r--r-- | deps/v8/src/ia32/lithium-codegen-ia32.cc | 332 |
1 files changed, 240 insertions, 92 deletions
diff --git a/deps/v8/src/ia32/lithium-codegen-ia32.cc b/deps/v8/src/ia32/lithium-codegen-ia32.cc index 9e4bada4f4..a59b1a5bad 100644 --- a/deps/v8/src/ia32/lithium-codegen-ia32.cc +++ b/deps/v8/src/ia32/lithium-codegen-ia32.cc @@ -43,13 +43,20 @@ class SafepointGenerator : public PostCallGenerator { public: SafepointGenerator(LCodeGen* codegen, LPointerMap* pointers, - int deoptimization_index) + int deoptimization_index, + bool ensure_reloc_space = false) : codegen_(codegen), pointers_(pointers), - deoptimization_index_(deoptimization_index) { } + deoptimization_index_(deoptimization_index), + ensure_reloc_space_(ensure_reloc_space) { } virtual ~SafepointGenerator() { } virtual void Generate() { + // Ensure that we have enough space in the reloc info to patch + // this with calls when doing deoptimization. + if (ensure_reloc_space_) { + codegen_->masm()->RecordComment(RelocInfo::kFillerCommentString, true); + } codegen_->RecordSafepoint(pointers_, deoptimization_index_); } @@ -57,6 +64,7 @@ class SafepointGenerator : public PostCallGenerator { LCodeGen* codegen_; LPointerMap* pointers_; int deoptimization_index_; + bool ensure_reloc_space_; }; @@ -157,6 +165,8 @@ bool LCodeGen::GeneratePrologue() { // Trace the call. if (FLAG_trace) { + // We have not executed any compiled code yet, so esi still holds the + // incoming context. __ CallRuntime(Runtime::kTraceEnter, 0); } return !is_aborted(); @@ -367,10 +377,14 @@ void LCodeGen::AddToTranslation(Translation* translation, void LCodeGen::CallCode(Handle<Code> code, RelocInfo::Mode mode, - LInstruction* instr) { + LInstruction* instr, + bool adjusted) { ASSERT(instr != NULL); LPointerMap* pointers = instr->pointer_map(); RecordPosition(pointers->position()); + if (!adjusted) { + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); + } __ call(code, mode); RegisterLazyDeoptimization(instr); @@ -383,15 +397,19 @@ void LCodeGen::CallCode(Handle<Code> code, } -void LCodeGen::CallRuntime(Runtime::Function* function, - int num_arguments, - LInstruction* instr) { +void LCodeGen::CallRuntime(Runtime::Function* fun, + int argc, + LInstruction* instr, + bool adjusted) { ASSERT(instr != NULL); ASSERT(instr->HasPointerMap()); LPointerMap* pointers = instr->pointer_map(); RecordPosition(pointers->position()); - __ CallRuntime(function, num_arguments); + if (!adjusted) { + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); + } + __ CallRuntime(fun, argc); RegisterLazyDeoptimization(instr); } @@ -568,10 +586,6 @@ void LCodeGen::RecordSafepoint( safepoint.DefinePointerRegister(ToRegister(pointer)); } } - if (kind & Safepoint::kWithRegisters) { - // Register esi always contains a pointer to the context. - safepoint.DefinePointerRegister(esi); - } } @@ -635,6 +649,7 @@ void LCodeGen::DoParameter(LParameter* instr) { void LCodeGen::DoCallStub(LCallStub* instr) { + ASSERT(ToRegister(instr->context()).is(esi)); ASSERT(ToRegister(instr->result()).is(eax)); switch (instr->hydrogen()->major_key()) { case CodeStub::RegExpConstructResult: { @@ -804,7 +819,7 @@ void LCodeGen::DoMulI(LMulI* instr) { __ test(left, Operand(left)); __ j(not_zero, &done); if (right->IsConstantOperand()) { - if (ToInteger32(LConstantOperand::cast(right)) < 0) { + if (ToInteger32(LConstantOperand::cast(right)) <= 0) { DeoptimizeIf(no_condition, instr->environment()); } } else { @@ -945,19 +960,31 @@ void LCodeGen::DoConstantD(LConstantD* instr) { if (BitCast<uint64_t, double>(v) == 0) { __ xorpd(res, res); } else { - int32_t v_int32 = static_cast<int32_t>(v); - if (static_cast<double>(v_int32) == v) { - __ push_imm32(v_int32); - __ cvtsi2sd(res, Operand(esp, 0)); - __ add(Operand(esp), Immediate(kPointerSize)); + Register temp = ToRegister(instr->TempAt(0)); + uint64_t int_val = BitCast<uint64_t, double>(v); + int32_t lower = static_cast<int32_t>(int_val); + int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); + if (CpuFeatures::IsSupported(SSE4_1)) { + CpuFeatures::Scope scope(SSE4_1); + if (lower != 0) { + __ Set(temp, Immediate(lower)); + __ movd(res, Operand(temp)); + __ Set(temp, Immediate(upper)); + __ pinsrd(res, Operand(temp), 1); + } else { + __ xorpd(res, res); + __ Set(temp, Immediate(upper)); + __ pinsrd(res, Operand(temp), 1); + } } else { - uint64_t int_val = BitCast<uint64_t, double>(v); - int32_t lower = static_cast<int32_t>(int_val); - int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); - __ push_imm32(upper); - __ push_imm32(lower); - __ movdbl(res, Operand(esp, 0)); - __ add(Operand(esp), Immediate(2 * kPointerSize)); + __ Set(temp, Immediate(upper)); + __ movd(res, Operand(temp)); + __ psllq(res, 32); + if (lower != 0) { + __ Set(temp, Immediate(lower)); + __ movd(xmm0, Operand(temp)); + __ por(res, xmm0); + } } } } @@ -983,6 +1010,13 @@ void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) { } +void LCodeGen::DoPixelArrayLength(LPixelArrayLength* instr) { + Register result = ToRegister(instr->result()); + Register array = ToRegister(instr->InputAt(0)); + __ mov(result, FieldOperand(array, PixelArray::kLengthOffset)); +} + + void LCodeGen::DoValueOf(LValueOf* instr) { Register input = ToRegister(instr->InputAt(0)); Register result = ToRegister(instr->result()); @@ -1011,7 +1045,7 @@ void LCodeGen::DoBitNotI(LBitNotI* instr) { void LCodeGen::DoThrow(LThrow* instr) { __ push(ToOperand(instr->InputAt(0))); - CallRuntime(Runtime::kThrow, 1, instr); + CallRuntime(Runtime::kThrow, 1, instr, false); if (FLAG_debug_code) { Comment("Unreachable code."); @@ -1083,7 +1117,7 @@ void LCodeGen::DoArithmeticT(LArithmeticT* instr) { ASSERT(ToRegister(instr->result()).is(eax)); TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE); - CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); + CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false); } @@ -1196,6 +1230,7 @@ void LCodeGen::EmitGoto(int block, LDeferredCode* deferred_stack_check) { void LCodeGen::DoDeferredStackCheck(LGoto* instr) { __ pushad(); + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); __ CallRuntimeSaveDoubles(Runtime::kStackGuard); RecordSafepointWithRegisters( instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); @@ -1686,6 +1721,7 @@ void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { void LCodeGen::DoInstanceOf(LInstanceOf* instr) { // Object and function are in fixed registers defined by the stub. + ASSERT(ToRegister(instr->context()).is(esi)); InstanceofStub stub(InstanceofStub::kArgsInRegisters); CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); @@ -1701,6 +1737,7 @@ void LCodeGen::DoInstanceOf(LInstanceOf* instr) { void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { + ASSERT(ToRegister(instr->context()).is(esi)); int true_block = chunk_->LookupDestination(instr->true_block_id()); int false_block = chunk_->LookupDestination(instr->false_block_id()); @@ -1735,11 +1772,11 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { Register object = ToRegister(instr->InputAt(0)); Register temp = ToRegister(instr->TempAt(0)); - // A Smi is not instance of anything. + // A Smi is not an instance of anything. __ test(object, Immediate(kSmiTagMask)); __ j(zero, &false_result, not_taken); - // This is the inlined call site instanceof cache. The two occourences of the + // This is the inlined call site instanceof cache. The two occurences of the // hole value will be patched to the last map/result pair generated by the // instanceof stub. NearLabel cache_miss; @@ -1751,10 +1788,10 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { __ mov(eax, Factory::the_hole_value()); // Patched to either true or false. __ jmp(&done); - // The inlined call site cache did not match. Check null and string before - // calling the deferred code. + // The inlined call site cache did not match. Check for null and string + // before calling the deferred code. __ bind(&cache_miss); - // Null is not instance of anything. + // Null is not an instance of anything. __ cmp(object, Factory::null_value()); __ j(equal, &false_result); @@ -1794,12 +1831,13 @@ void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, Register temp = ToRegister(instr->TempAt(0)); ASSERT(temp.is(edi)); __ mov(InstanceofStub::right(), Immediate(instr->function())); - static const int kAdditionalDelta = 13; + static const int kAdditionalDelta = 16; int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; Label before_push_delta; __ bind(&before_push_delta); __ mov(temp, Immediate(delta)); __ mov(Operand(esp, EspIndexForPushAll(temp) * kPointerSize), temp); + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); __ call(stub.GetCode(), RelocInfo::CODE_TARGET); ASSERT_EQ(kAdditionalDelta, masm_->SizeOfCodeGeneratedSince(&before_push_delta)); @@ -1836,7 +1874,7 @@ void LCodeGen::DoCmpT(LCmpT* instr) { Token::Value op = instr->op(); Handle<Code> ic = CompareIC::GetUninitialized(op); - CallCode(ic, RelocInfo::CODE_TARGET, instr); + CallCode(ic, RelocInfo::CODE_TARGET, instr, false); Condition condition = ComputeCompareCondition(op); if (op == Token::GT || op == Token::LTE) { @@ -1859,7 +1897,7 @@ void LCodeGen::DoCmpTAndBranch(LCmpTAndBranch* instr) { int false_block = chunk_->LookupDestination(instr->false_block_id()); Handle<Code> ic = CompareIC::GetUninitialized(op); - CallCode(ic, RelocInfo::CODE_TARGET, instr); + CallCode(ic, RelocInfo::CODE_TARGET, instr, false); // The compare stub expects compare condition and the input operands // reversed for GT and LTE. @@ -1874,14 +1912,17 @@ void LCodeGen::DoCmpTAndBranch(LCmpTAndBranch* instr) { void LCodeGen::DoReturn(LReturn* instr) { if (FLAG_trace) { - // Preserve the return value on the stack and rely on the runtime - // call to return the value in the same register. + // Preserve the return value on the stack and rely on the runtime call + // to return the value in the same register. We're leaving the code + // managed by the register allocator and tearing down the frame, it's + // safe to write to the context register. __ push(eax); + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); __ CallRuntime(Runtime::kTraceExit, 1); } __ mov(esp, ebp); __ pop(ebp); - __ ret((ParameterCount() + 1) * kPointerSize); + __ Ret((ParameterCount() + 1) * kPointerSize, ecx); } @@ -1945,6 +1986,7 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { + ASSERT(ToRegister(instr->context()).is(esi)); ASSERT(ToRegister(instr->object()).is(eax)); ASSERT(ToRegister(instr->result()).is(eax)); @@ -1997,22 +2039,33 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { void LCodeGen::DoLoadElements(LLoadElements* instr) { - ASSERT(instr->result()->Equals(instr->InputAt(0))); - Register reg = ToRegister(instr->InputAt(0)); - __ mov(reg, FieldOperand(reg, JSObject::kElementsOffset)); + Register result = ToRegister(instr->result()); + Register input = ToRegister(instr->InputAt(0)); + __ mov(result, FieldOperand(input, JSObject::kElementsOffset)); if (FLAG_debug_code) { NearLabel done; - __ cmp(FieldOperand(reg, HeapObject::kMapOffset), + __ cmp(FieldOperand(result, HeapObject::kMapOffset), Immediate(Factory::fixed_array_map())); __ j(equal, &done); - __ cmp(FieldOperand(reg, HeapObject::kMapOffset), + __ cmp(FieldOperand(result, HeapObject::kMapOffset), + Immediate(Factory::pixel_array_map())); + __ j(equal, &done); + __ cmp(FieldOperand(result, HeapObject::kMapOffset), Immediate(Factory::fixed_cow_array_map())); - __ Check(equal, "Check for fast elements failed."); + __ Check(equal, "Check for fast elements or pixel array failed."); __ bind(&done); } } +void LCodeGen::DoLoadPixelArrayExternalPointer( + LLoadPixelArrayExternalPointer* instr) { + Register result = ToRegister(instr->result()); + Register input = ToRegister(instr->InputAt(0)); + __ mov(result, FieldOperand(input, PixelArray::kExternalPointerOffset)); +} + + void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { Register arguments = ToRegister(instr->arguments()); Register length = ToRegister(instr->length()); @@ -2035,7 +2088,10 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { ASSERT(result.is(elements)); // Load the result. - __ mov(result, FieldOperand(elements, key, times_4, FixedArray::kHeaderSize)); + __ mov(result, FieldOperand(elements, + key, + times_pointer_size, + FixedArray::kHeaderSize)); // Check for the hole value. __ cmp(result, Factory::the_hole_value()); @@ -2043,7 +2099,19 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { } +void LCodeGen::DoLoadPixelArrayElement(LLoadPixelArrayElement* instr) { + Register external_elements = ToRegister(instr->external_pointer()); + Register key = ToRegister(instr->key()); + Register result = ToRegister(instr->result()); + ASSERT(result.is(external_elements)); + + // Load the result. + __ movzx_b(result, Operand(external_elements, key, times_1, 0)); +} + + void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { + ASSERT(ToRegister(instr->context()).is(esi)); ASSERT(ToRegister(instr->object()).is(edx)); ASSERT(ToRegister(instr->key()).is(eax)); @@ -2101,24 +2169,36 @@ void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { void LCodeGen::DoApplyArguments(LApplyArguments* instr) { Register receiver = ToRegister(instr->receiver()); - ASSERT(ToRegister(instr->function()).is(edi)); + Register function = ToRegister(instr->function()); + Register length = ToRegister(instr->length()); + Register elements = ToRegister(instr->elements()); + Register scratch = ToRegister(instr->TempAt(0)); + ASSERT(receiver.is(eax)); // Used for parameter count. + ASSERT(function.is(edi)); // Required by InvokeFunction. ASSERT(ToRegister(instr->result()).is(eax)); - // If the receiver is null or undefined, we have to pass the - // global object as a receiver. - NearLabel global_receiver, receiver_ok; + // If the receiver is null or undefined, we have to pass the global object + // as a receiver. + NearLabel global_object, receiver_ok; __ cmp(receiver, Factory::null_value()); - __ j(equal, &global_receiver); + __ j(equal, &global_object); __ cmp(receiver, Factory::undefined_value()); - __ j(not_equal, &receiver_ok); - __ bind(&global_receiver); - __ mov(receiver, GlobalObjectOperand()); - __ bind(&receiver_ok); + __ j(equal, &global_object); - Register length = ToRegister(instr->length()); - Register elements = ToRegister(instr->elements()); - - Label invoke; + // The receiver should be a JS object. + __ test(receiver, Immediate(kSmiTagMask)); + DeoptimizeIf(equal, instr->environment()); + __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, scratch); + DeoptimizeIf(below, instr->environment()); + __ jmp(&receiver_ok); + + __ bind(&global_object); + // TODO(kmillikin): We have a hydrogen value for the global object. See + // if it's better to use it than to explicitly fetch it from the context + // here. + __ mov(receiver, Operand(ebp, StandardFrameConstants::kContextOffset)); + __ mov(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX)); + __ bind(&receiver_ok); // Copy the arguments to this function possibly from the // adaptor frame below it. @@ -2131,7 +2211,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) { // Loop through the arguments pushing them onto the execution // stack. - Label loop; + NearLabel invoke, loop; // length is a small non-negative integer, due to the test above. __ test(length, Operand(length)); __ j(zero, &invoke); @@ -2149,13 +2229,10 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) { RegisterEnvironmentForDeoptimization(env); SafepointGenerator safepoint_generator(this, pointers, - env->deoptimization_index()); - ASSERT(receiver.is(eax)); + env->deoptimization_index(), + true); v8::internal::ParameterCount actual(eax); - __ InvokeFunction(edi, actual, CALL_FUNCTION, &safepoint_generator); - - // Restore context. - __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); + __ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator); } @@ -2171,7 +2248,7 @@ void LCodeGen::DoPushArgument(LPushArgument* instr) { void LCodeGen::DoContext(LContext* instr) { Register result = ToRegister(instr->result()); - __ mov(result, esi); + __ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset)); } @@ -2207,6 +2284,8 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function, (scope()->num_heap_slots() > 0); if (change_context) { __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); + } else { + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); } // Set eax to arguments count if adaption is not needed. Assumes that eax @@ -2222,14 +2301,15 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function, if (*function == *graph()->info()->closure()) { __ CallSelf(); } else { + // This is an indirect call and will not be recorded in the reloc info. + // Add a comment to the reloc info in case we need to patch this during + // deoptimization. + __ RecordComment(RelocInfo::kFillerCommentString, true); __ call(FieldOperand(edi, JSFunction::kCodeEntryOffset)); } // Setup deoptimization. RegisterLazyDeoptimization(instr); - - // Restore context. - __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); } @@ -2272,6 +2352,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { // Slow case: Call the runtime system to do the number allocation. __ bind(&slow); + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); RecordSafepointWithRegisters( instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); @@ -2483,7 +2564,7 @@ void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); TranscendentalCacheStub stub(TranscendentalCache::LOG, TranscendentalCacheStub::UNTAGGED); - CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); + CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false); } @@ -2491,7 +2572,7 @@ void LCodeGen::DoMathCos(LUnaryMathOperation* instr) { ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); TranscendentalCacheStub stub(TranscendentalCache::COS, TranscendentalCacheStub::UNTAGGED); - CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); + CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false); } @@ -2499,7 +2580,7 @@ void LCodeGen::DoMathSin(LUnaryMathOperation* instr) { ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); TranscendentalCacheStub stub(TranscendentalCache::SIN, TranscendentalCacheStub::UNTAGGED); - CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); + CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false); } @@ -2537,46 +2618,46 @@ void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { void LCodeGen::DoCallKeyed(LCallKeyed* instr) { + ASSERT(ToRegister(instr->context()).is(esi)); + ASSERT(ToRegister(instr->key()).is(ecx)); ASSERT(ToRegister(instr->result()).is(eax)); - ASSERT(ToRegister(instr->InputAt(0)).is(ecx)); int arity = instr->arity(); Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arity, NOT_IN_LOOP); CallCode(ic, RelocInfo::CODE_TARGET, instr); - __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); } void LCodeGen::DoCallNamed(LCallNamed* instr) { + ASSERT(ToRegister(instr->context()).is(esi)); ASSERT(ToRegister(instr->result()).is(eax)); int arity = instr->arity(); Handle<Code> ic = StubCache::ComputeCallInitialize(arity, NOT_IN_LOOP); __ mov(ecx, instr->name()); CallCode(ic, RelocInfo::CODE_TARGET, instr); - __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); } void LCodeGen::DoCallFunction(LCallFunction* instr) { + ASSERT(ToRegister(instr->context()).is(esi)); ASSERT(ToRegister(instr->result()).is(eax)); int arity = instr->arity(); CallFunctionStub stub(arity, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE); CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); __ Drop(1); - __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); } void LCodeGen::DoCallGlobal(LCallGlobal* instr) { + ASSERT(ToRegister(instr->context()).is(esi)); ASSERT(ToRegister(instr->result()).is(eax)); int arity = instr->arity(); Handle<Code> ic = StubCache::ComputeCallInitialize(arity, NOT_IN_LOOP); __ mov(ecx, instr->name()); CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); - __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); } @@ -2588,7 +2669,8 @@ void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { void LCodeGen::DoCallNew(LCallNew* instr) { - ASSERT(ToRegister(instr->InputAt(0)).is(edi)); + ASSERT(ToRegister(instr->context()).is(esi)); + ASSERT(ToRegister(instr->constructor()).is(edi)); ASSERT(ToRegister(instr->result()).is(eax)); Handle<Code> builtin(Builtins::builtin(Builtins::JSConstructCall)); @@ -2598,7 +2680,7 @@ void LCodeGen::DoCallNew(LCallNew* instr) { void LCodeGen::DoCallRuntime(LCallRuntime* instr) { - CallRuntime(instr->function(), instr->arity(), instr); + CallRuntime(instr->function(), instr->arity(), instr, false); } @@ -2633,6 +2715,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { + ASSERT(ToRegister(instr->context()).is(esi)); ASSERT(ToRegister(instr->object()).is(edx)); ASSERT(ToRegister(instr->value()).is(eax)); @@ -2661,19 +2744,27 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { ToInteger32(const_operand) * kPointerSize + FixedArray::kHeaderSize; __ mov(FieldOperand(elements, offset), value); } else { - __ mov(FieldOperand(elements, key, times_4, FixedArray::kHeaderSize), + __ mov(FieldOperand(elements, + key, + times_pointer_size, + FixedArray::kHeaderSize), value); } if (instr->hydrogen()->NeedsWriteBarrier()) { // Compute address of modified element and store it into key register. - __ lea(key, FieldOperand(elements, key, times_4, FixedArray::kHeaderSize)); + __ lea(key, + FieldOperand(elements, + key, + times_pointer_size, + FixedArray::kHeaderSize)); __ RecordWrite(elements, key, value); } } void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { + ASSERT(ToRegister(instr->context()).is(esi)); ASSERT(ToRegister(instr->object()).is(edx)); ASSERT(ToRegister(instr->key()).is(ecx)); ASSERT(ToRegister(instr->value()).is(eax)); @@ -2809,6 +2900,7 @@ void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { __ SmiTag(index); __ push(index); } + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); __ CallRuntimeSaveDoubles(Runtime::kStringCharCodeAt); RecordSafepointWithRegisters( instr->pointer_map(), 2, Safepoint::kNoDeoptimizationIndex); @@ -2886,6 +2978,7 @@ void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { // integer value. __ mov(Operand(esp, EspIndexForPushAll(reg) * kPointerSize), Immediate(0)); + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); RecordSafepointWithRegisters( instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); @@ -2933,6 +3026,7 @@ void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { __ Set(reg, Immediate(0)); __ PushSafepointRegisters(); + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); RecordSafepointWithRegisters( instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); @@ -3348,21 +3442,22 @@ void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { FastCloneShallowArrayStub::Mode mode = FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS; FastCloneShallowArrayStub stub(mode, length); - CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); + CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false); } else if (instr->hydrogen()->depth() > 1) { - CallRuntime(Runtime::kCreateArrayLiteral, 3, instr); + CallRuntime(Runtime::kCreateArrayLiteral, 3, instr, false); } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { - CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr); + CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr, false); } else { FastCloneShallowArrayStub::Mode mode = FastCloneShallowArrayStub::CLONE_ELEMENTS; FastCloneShallowArrayStub stub(mode, length); - CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); + CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false); } } void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) { + ASSERT(ToRegister(instr->context()).is(esi)); // Setup the parameters to the stub/runtime call. __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); __ push(FieldOperand(eax, JSFunction::kLiteralsOffset)); @@ -3400,7 +3495,7 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); __ push(Immediate(instr->hydrogen()->pattern())); __ push(Immediate(instr->hydrogen()->flags())); - CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); + CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr, false); __ mov(ebx, eax); __ bind(&materialized); @@ -3412,7 +3507,7 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { __ bind(&runtime_allocate); __ push(ebx); __ push(Immediate(Smi::FromInt(size))); - CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); + CallRuntime(Runtime::kAllocateInNewSpace, 1, instr, false); __ pop(ebx); __ bind(&allocated); @@ -3439,14 +3534,14 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { if (shared_info->num_literals() == 0 && !pretenure) { FastNewClosureStub stub; __ push(Immediate(shared_info)); - CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); + CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false); } else { - __ push(esi); + __ push(Operand(ebp, StandardFrameConstants::kContextOffset)); __ push(Immediate(shared_info)); __ push(Immediate(pretenure ? Factory::true_value() : Factory::false_value())); - CallRuntime(Runtime::kNewClosure, 3, instr); + CallRuntime(Runtime::kNewClosure, 3, instr, false); } } @@ -3458,7 +3553,7 @@ void LCodeGen::DoTypeof(LTypeof* instr) { } else { __ push(ToOperand(input)); } - CallRuntime(Runtime::kTypeof, 1, instr); + CallRuntime(Runtime::kTypeof, 1, instr, false); } @@ -3577,6 +3672,53 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label, } +void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) { + Register result = ToRegister(instr->result()); + NearLabel true_label; + NearLabel false_label; + NearLabel done; + + EmitIsConstructCall(result); + __ j(equal, &true_label); + + __ mov(result, Factory::false_value()); + __ jmp(&done); + + __ bind(&true_label); + __ mov(result, Factory::true_value()); + + __ bind(&done); +} + + +void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { + Register temp = ToRegister(instr->TempAt(0)); + int true_block = chunk_->LookupDestination(instr->true_block_id()); + int false_block = chunk_->LookupDestination(instr->false_block_id()); + + EmitIsConstructCall(temp); + EmitBranch(true_block, false_block, equal); +} + + +void LCodeGen::EmitIsConstructCall(Register temp) { + // Get the frame pointer for the calling frame. + __ mov(temp, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); + + // Skip the arguments adaptor frame if it exists. + NearLabel check_frame_marker; + __ cmp(Operand(temp, StandardFrameConstants::kContextOffset), + Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); + __ j(not_equal, &check_frame_marker); + __ mov(temp, Operand(temp, StandardFrameConstants::kCallerFPOffset)); + + // Check the marker in the calling frame. + __ bind(&check_frame_marker); + __ cmp(Operand(temp, StandardFrameConstants::kMarkerOffset), + Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); +} + + void LCodeGen::DoLazyBailout(LLazyBailout* instr) { // No code for lazy bailout instruction. Used to capture environment after a // call for populating the safepoint data with deoptimization data. @@ -3602,9 +3744,15 @@ void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) { LEnvironment* env = instr->deoptimization_environment(); RecordPosition(pointers->position()); RegisterEnvironmentForDeoptimization(env); + // Create safepoint generator that will also ensure enough space in the + // reloc info for patching in deoptimization (since this is invoking a + // builtin) SafepointGenerator safepoint_generator(this, pointers, - env->deoptimization_index()); + env->deoptimization_index(), + true); + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); + __ push(Immediate(Smi::FromInt(strict_mode_flag()))); __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, &safepoint_generator); } @@ -3617,7 +3765,7 @@ void LCodeGen::DoStackCheck(LStackCheck* instr) { __ j(above_equal, &done); StackCheckStub stub; - CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); + CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false); __ bind(&done); } |