diff options
Diffstat (limited to 'deps/v8/src/x64/lithium-codegen-x64.cc')
-rw-r--r-- | deps/v8/src/x64/lithium-codegen-x64.cc | 458 |
1 files changed, 218 insertions, 240 deletions
diff --git a/deps/v8/src/x64/lithium-codegen-x64.cc b/deps/v8/src/x64/lithium-codegen-x64.cc index 9dca6b3e20..7c70094fbf 100644 --- a/deps/v8/src/x64/lithium-codegen-x64.cc +++ b/deps/v8/src/x64/lithium-codegen-x64.cc @@ -89,9 +89,7 @@ void LCodeGen::FinishCode(Handle<Code> code) { ASSERT(is_done()); code->set_stack_slots(GetStackSlotCount()); code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); - if (FLAG_weak_embedded_maps_in_optimized_code) { - RegisterDependentCodeForEmbeddedMaps(code); - } + RegisterDependentCodeForEmbeddedMaps(code); PopulateDeoptimizationData(code); info()->CommitDependencies(code); } @@ -103,24 +101,6 @@ void LChunkBuilder::Abort(BailoutReason reason) { } -void LCodeGen::Comment(const char* format, ...) { - if (!FLAG_code_comments) return; - char buffer[4 * KB]; - StringBuilder builder(buffer, ARRAY_SIZE(buffer)); - va_list arguments; - va_start(arguments, format); - builder.AddFormattedList(format, arguments); - va_end(arguments); - - // Copy the string before recording it in the assembler to avoid - // issues when the stack allocated buffer goes out of scope. - int length = builder.position(); - Vector<char> copy = Vector<char>::New(length + 1); - OS::MemCopy(copy.start(), builder.Finalize(), copy.length()); - masm()->RecordComment(copy.start()); -} - - #ifdef _MSC_VER void LCodeGen::MakeSureStackPagesMapped(int offset) { const int kPageSize = 4 * KB; @@ -152,10 +132,9 @@ bool LCodeGen::GeneratePrologue() { Label ok; __ testq(rcx, rcx); __ j(zero, &ok, Label::kNear); - // +1 for return address. - int receiver_offset = (scope()->num_parameters() + 1) * kPointerSize; + StackArgumentsAccessor args(rsp, scope()->num_parameters()); __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); - __ movq(Operand(rsp, receiver_offset), kScratchRegister); + __ movq(args.GetReceiverOperand(), kScratchRegister); __ bind(&ok); } } @@ -164,14 +143,7 @@ bool LCodeGen::GeneratePrologue() { if (NeedsEagerFrame()) { ASSERT(!frame_is_built_); frame_is_built_ = true; - __ push(rbp); // Caller's frame pointer. - __ movq(rbp, rsp); - __ push(rsi); // Callee's context. - if (info()->IsStub()) { - __ Push(Smi::FromInt(StackFrame::STUB)); - } else { - __ push(rdi); // Callee's JS function. - } + __ Prologue(info()->IsStub() ? BUILD_STUB_FRAME : BUILD_FUNCTION_FRAME); info()->AddNoFrameRange(0, masm_->pc_offset()); } @@ -273,36 +245,6 @@ void LCodeGen::GenerateOsrPrologue() { } -bool LCodeGen::GenerateBody() { - ASSERT(is_generating()); - bool emit_instructions = true; - for (current_instruction_ = 0; - !is_aborted() && current_instruction_ < instructions_->length(); - current_instruction_++) { - LInstruction* instr = instructions_->at(current_instruction_); - - // Don't emit code for basic blocks with a replacement. - if (instr->IsLabel()) { - emit_instructions = !LLabel::cast(instr)->HasReplacement(); - } - if (!emit_instructions) continue; - - if (FLAG_code_comments && instr->HasInterestingComment(this)) { - Comment(";;; <@%d,#%d> %s", - current_instruction_, - instr->hydrogen_value()->id(), - instr->Mnemonic()); - } - - RecordAndUpdatePosition(instr->position()); - - instr->CompileToNative(this); - } - EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); - return !is_aborted(); -} - - bool LCodeGen::GenerateJumpTable() { Label needs_frame; if (jump_table_.length() > 0) { @@ -350,8 +292,9 @@ bool LCodeGen::GenerateDeferredCode() { for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { LDeferredCode* code = deferred_[i]; - int pos = instructions_->at(code->instruction_index())->position(); - RecordAndUpdatePosition(pos); + HValue* value = + instructions_->at(code->instruction_index())->hydrogen_value(); + RecordAndWritePosition(value->position()); Comment(";;; <@%d,#%d> " "-------------------- Deferred %s --------------------", @@ -614,8 +557,6 @@ void LCodeGen::CallCodeGeneric(Handle<Code> code, int argc) { EnsureSpaceForLazyDeopt(Deoptimizer::patch_size() - masm()->CallSize(code)); ASSERT(instr != NULL); - LPointerMap* pointers = instr->pointer_map(); - RecordPosition(pointers->position()); __ call(code, mode); RecordSafepointWithLazyDeopt(instr, safepoint_mode, argc); @@ -637,13 +578,13 @@ void LCodeGen::CallCode(Handle<Code> code, void LCodeGen::CallRuntime(const Runtime::Function* function, int num_arguments, - LInstruction* instr) { + LInstruction* instr, + SaveFPRegsMode save_doubles) { ASSERT(instr != NULL); ASSERT(instr->HasPointerMap()); - LPointerMap* pointers = instr->pointer_map(); - RecordPosition(pointers->position()); - __ CallRuntime(function, num_arguments); + __ CallRuntime(function, num_arguments, save_doubles); + RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0); } @@ -754,26 +695,31 @@ void LCodeGen::DeoptimizeIf(Condition cc, void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) { ZoneList<Handle<Map> > maps(1, zone()); + ZoneList<Handle<JSObject> > objects(1, zone()); int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { - RelocInfo::Mode mode = it.rinfo()->rmode(); - if (mode == RelocInfo::EMBEDDED_OBJECT && - it.rinfo()->target_object()->IsMap()) { - Handle<Map> map(Map::cast(it.rinfo()->target_object())); - if (map->CanTransition()) { + if (Code::IsWeakEmbeddedObject(code->kind(), it.rinfo()->target_object())) { + if (it.rinfo()->target_object()->IsMap()) { + Handle<Map> map(Map::cast(it.rinfo()->target_object())); maps.Add(map, zone()); + } else if (it.rinfo()->target_object()->IsJSObject()) { + Handle<JSObject> object(JSObject::cast(it.rinfo()->target_object())); + objects.Add(object, zone()); } } } #ifdef VERIFY_HEAP - // This disables verification of weak embedded maps after full GC. + // This disables verification of weak embedded objects after full GC. // AddDependentCode can cause a GC, which would observe the state where // this code is not yet in the depended code lists of the embedded maps. - NoWeakEmbeddedMapsVerificationScope disable_verification_of_embedded_maps; + NoWeakObjectVerificationScope disable_verification_of_embedded_objects; #endif for (int i = 0; i < maps.length(); i++) { maps.at(i)->AddDependentCode(DependentCode::kWeaklyEmbeddedGroup, code); } + for (int i = 0; i < objects.length(); i++) { + AddWeakObjectToCodeDependency(isolate()->heap(), objects.at(i), code); + } } @@ -884,7 +830,7 @@ void LCodeGen::RecordSafepoint(LPointerMap* pointers, void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) { - LPointerMap empty_pointers(RelocInfo::kNoPosition, zone()); + LPointerMap empty_pointers(zone()); RecordSafepoint(&empty_pointers, deopt_mode); } @@ -896,17 +842,10 @@ void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, } -void LCodeGen::RecordPosition(int position) { +void LCodeGen::RecordAndWritePosition(int position) { if (position == RelocInfo::kNoPosition) return; masm()->positions_recorder()->RecordPosition(position); -} - - -void LCodeGen::RecordAndUpdatePosition(int position) { - if (position >= 0 && position != old_position_) { - masm()->positions_recorder()->RecordPosition(position); - old_position_ = position; - } + masm()->positions_recorder()->WriteRecordedPositions(); } @@ -973,11 +912,6 @@ void LCodeGen::DoCallStub(LCallStub* instr) { CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); break; } - case CodeStub::NumberToString: { - NumberToStringStub stub; - CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); - break; - } case CodeStub::StringCompare: { StringCompareStub stub; CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); @@ -1615,8 +1549,7 @@ void LCodeGen::DoConstantE(LConstantE* instr) { void LCodeGen::DoConstantT(LConstantT* instr) { Handle<Object> value = instr->value(isolate()); - AllowDeferredHandleDereference smi_check; - __ LoadObject(ToRegister(instr->result()), value); + __ Move(ToRegister(instr->result()), value); } @@ -1832,7 +1765,7 @@ void LCodeGen::DoMathMinMax(LMathMinMax* instr) { __ jmp(&return_right, Label::kNear); __ bind(&check_zero); - XMMRegister xmm_scratch = xmm0; + XMMRegister xmm_scratch = double_scratch0(); __ xorps(xmm_scratch, xmm_scratch); __ ucomisd(left_reg, xmm_scratch); __ j(not_equal, &return_left, Label::kNear); // left == right != 0. @@ -1878,15 +1811,17 @@ void LCodeGen::DoArithmeticD(LArithmeticD* instr) { // when there is a mulsd depending on the result __ movaps(left, left); break; - case Token::MOD: + case Token::MOD: { + XMMRegister xmm_scratch = double_scratch0(); __ PrepareCallCFunction(2); - __ movaps(xmm0, left); + __ movaps(xmm_scratch, left); ASSERT(right.is(xmm1)); __ CallCFunction( ExternalReference::double_fp_operation(Token::MOD, isolate()), 2); __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); - __ movaps(result, xmm0); + __ movaps(result, xmm_scratch); break; + } default: UNREACHABLE(); break; @@ -1905,14 +1840,6 @@ void LCodeGen::DoArithmeticT(LArithmeticT* instr) { } -int LCodeGen::GetNextEmittedBlock() const { - for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { - if (!chunk_->GetLabel(i)->HasReplacement()) return i; - } - return -1; -} - - template<class InstrType> void LCodeGen::EmitBranch(InstrType instr, Condition cc) { int left_block = instr->TrueDestination(chunk_); @@ -1947,25 +1874,6 @@ void LCodeGen::DoDebugBreak(LDebugBreak* instr) { } -void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) { - Representation r = instr->hydrogen()->value()->representation(); - if (r.IsSmiOrInteger32() || r.IsDouble()) { - EmitBranch(instr, no_condition); - } else { - ASSERT(r.IsTagged()); - Register reg = ToRegister(instr->value()); - HType type = instr->hydrogen()->value()->type(); - if (type.IsTaggedNumber()) { - EmitBranch(instr, no_condition); - } - __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); - __ CompareRoot(FieldOperand(reg, HeapObject::kMapOffset), - Heap::kHeapNumberMapRootIndex); - EmitBranch(instr, equal); - } -} - - void LCodeGen::DoBranch(LBranch* instr) { Representation r = instr->hydrogen()->value()->representation(); if (r.IsInteger32()) { @@ -1981,8 +1889,9 @@ void LCodeGen::DoBranch(LBranch* instr) { } else if (r.IsDouble()) { ASSERT(!info()->IsStub()); XMMRegister reg = ToDoubleRegister(instr->value()); - __ xorps(xmm0, xmm0); - __ ucomisd(reg, xmm0); + XMMRegister xmm_scratch = double_scratch0(); + __ xorps(xmm_scratch, xmm_scratch); + __ ucomisd(reg, xmm_scratch); EmitBranch(instr, not_equal); } else { ASSERT(r.IsTagged()); @@ -2001,8 +1910,9 @@ void LCodeGen::DoBranch(LBranch* instr) { EmitBranch(instr, no_condition); } else if (type.IsHeapNumber()) { ASSERT(!info()->IsStub()); - __ xorps(xmm0, xmm0); - __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset)); + XMMRegister xmm_scratch = double_scratch0(); + __ xorps(xmm_scratch, xmm_scratch); + __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); EmitBranch(instr, not_equal); } else if (type.IsString()) { ASSERT(!info()->IsStub()); @@ -2083,8 +1993,9 @@ void LCodeGen::DoBranch(LBranch* instr) { Label not_heap_number; __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); __ j(not_equal, ¬_heap_number, Label::kNear); - __ xorps(xmm0, xmm0); - __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset)); + XMMRegister xmm_scratch = double_scratch0(); + __ xorps(xmm_scratch, xmm_scratch); + __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); __ j(zero, instr->FalseLabel(chunk_)); __ jmp(instr->TrueLabel(chunk_)); __ bind(¬_heap_number); @@ -2119,6 +2030,10 @@ inline Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { case Token::EQ_STRICT: cond = equal; break; + case Token::NE: + case Token::NE_STRICT: + cond = not_equal; + break; case Token::LT: cond = is_unsigned ? below : less; break; @@ -2206,7 +2121,7 @@ void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { if (instr->right()->IsConstantOperand()) { Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right())); - __ CmpObject(left, right); + __ Cmp(left, right); } else { Register right = ToRegister(instr->right()); __ cmpq(left, right); @@ -2574,7 +2489,7 @@ void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, InstanceofStub stub(flags); __ push(ToRegister(instr->value())); - __ PushHeapObject(instr->function()); + __ Push(instr->function()); static const int kAdditionalDelta = 10; int delta = @@ -2610,14 +2525,6 @@ void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, } -void LCodeGen::DoInstanceSize(LInstanceSize* instr) { - Register object = ToRegister(instr->object()); - Register result = ToRegister(instr->result()); - __ movq(result, FieldOperand(object, HeapObject::kMapOffset)); - __ movzxbq(result, FieldOperand(result, Map::kInstanceSizeOffset)); -} - - void LCodeGen::DoCmpT(LCmpT* instr) { Token::Value op = instr->op(); @@ -2682,7 +2589,7 @@ void LCodeGen::DoReturn(LReturn* instr) { void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { Register result = ToRegister(instr->result()); - __ LoadGlobalCell(result, instr->hydrogen()->cell()); + __ LoadGlobalCell(result, instr->hydrogen()->cell().handle()); if (instr->hydrogen()->RequiresHoleCheck()) { __ CompareRoot(result, Heap::kTheHoleValueRootIndex); DeoptimizeIf(equal, instr->environment()); @@ -2704,7 +2611,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { Register value = ToRegister(instr->value()); - Handle<Cell> cell_handle = instr->hydrogen()->cell(); + Handle<Cell> cell_handle = instr->hydrogen()->cell().handle(); // If the cell we are storing to contains the hole it could have // been deleted from the property dictionary. In that case, we need @@ -2805,7 +2712,7 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { __ load_rax(ToExternalReference(LConstantOperand::cast(instr->object()))); } else { Register object = ToRegister(instr->object()); - __ movq(result, MemOperand(object, offset)); + __ Load(result, MemOperand(object, offset), access.representation()); } return; } @@ -2819,12 +2726,11 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { } Register result = ToRegister(instr->result()); - if (access.IsInobject()) { - __ movq(result, FieldOperand(object, offset)); - } else { + if (!access.IsInobject()) { __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); - __ movq(result, FieldOperand(result, offset)); + object = result; } + __ Load(result, FieldOperand(object, offset), access.representation()); } @@ -2879,6 +2785,12 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { } +void LCodeGen::DoLoadRoot(LLoadRoot* instr) { + Register result = ToRegister(instr->result()); + __ LoadRoot(result, instr->index()); +} + + void LCodeGen::DoLoadExternalArrayPointer( LLoadExternalArrayPointer* instr) { Register result = ToRegister(instr->result()); @@ -2896,8 +2808,9 @@ void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { instr->index()->IsConstantOperand()) { int32_t const_index = ToInteger32(LConstantOperand::cast(instr->index())); int32_t const_length = ToInteger32(LConstantOperand::cast(instr->length())); - int index = (const_length - const_index) + 1; - __ movq(result, Operand(arguments, index * kPointerSize)); + StackArgumentsAccessor args(arguments, const_length, + ARGUMENTS_DONT_CONTAIN_RECEIVER); + __ movq(result, args.GetArgumentOperand(const_index)); } else { Register length = ToRegister(instr->length()); // There are two words between the frame pointer and the last argument. @@ -2907,8 +2820,9 @@ void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { } else { __ subl(length, ToOperand(instr->index())); } - __ movq(result, - Operand(arguments, length, times_pointer_size, kPointerSize)); + StackArgumentsAccessor args(arguments, length, + ARGUMENTS_DONT_CONTAIN_RECEIVER); + __ movq(result, args.GetArgumentOperand(0)); } } @@ -3112,7 +3026,7 @@ void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { Register result = ToRegister(instr->result()); if (instr->hydrogen()->from_inlined()) { - __ lea(result, Operand(rsp, -2 * kPointerSize)); + __ lea(result, Operand(rsp, -kFPOnStackSize + -kPCOnStackSize)); } else { // Check for arguments adapter frame. Label done, adapted; @@ -3234,7 +3148,9 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) { __ testl(length, length); __ j(zero, &invoke, Label::kNear); __ bind(&loop); - __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize)); + StackArgumentsAccessor args(elements, length, + ARGUMENTS_DONT_CONTAIN_RECEIVER); + __ push(args.GetArgumentOperand(0)); __ decl(length); __ j(not_zero, &loop); @@ -3242,7 +3158,6 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) { __ bind(&invoke); ASSERT(instr->HasPointerMap()); LPointerMap* pointers = instr->pointer_map(); - RecordPosition(pointers->position()); SafepointGenerator safepoint_generator( this, pointers, Safepoint::kLazyDeopt); ParameterCount actual(rax); @@ -3285,7 +3200,7 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) { void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { __ push(rsi); // The context is the first argument. - __ PushHeapObject(instr->hydrogen()->pairs()); + __ Push(instr->hydrogen()->pairs()); __ Push(Smi::FromInt(instr->hydrogen()->flags())); CallRuntime(Runtime::kDeclareGlobals, 3, instr); } @@ -3316,11 +3231,10 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function, dont_adapt_arguments || formal_parameter_count == arity; LPointerMap* pointers = instr->pointer_map(); - RecordPosition(pointers->position()); if (can_invoke_directly) { if (rdi_state == RDI_UNINITIALIZED) { - __ LoadHeapObject(rdi, function); + __ Move(rdi, function); } // Change context. @@ -3401,10 +3315,10 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { __ LoadFromSafepointRegisterSlot(input_reg, input_reg); __ bind(&allocated); - __ movq(tmp2, FieldOperand(input_reg, HeapNumber::kValueOffset)); + __ MoveDouble(tmp2, FieldOperand(input_reg, HeapNumber::kValueOffset)); __ shl(tmp2, Immediate(1)); __ shr(tmp2, Immediate(1)); - __ movq(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2); + __ MoveDouble(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2); __ StoreToSafepointRegisterSlot(input_reg, tmp); __ bind(&done); @@ -3451,11 +3365,11 @@ void LCodeGen::DoMathAbs(LMathAbs* instr) { Representation r = instr->hydrogen()->value()->representation(); if (r.IsDouble()) { - XMMRegister scratch = xmm0; + XMMRegister scratch = double_scratch0(); XMMRegister input_reg = ToDoubleRegister(instr->value()); __ xorps(scratch, scratch); __ subsd(scratch, input_reg); - __ andpd(input_reg, scratch); + __ andps(input_reg, scratch); } else if (r.IsInteger32()) { EmitIntegerMathAbs(instr); } else if (r.IsSmi()) { @@ -3473,7 +3387,7 @@ void LCodeGen::DoMathAbs(LMathAbs* instr) { void LCodeGen::DoMathFloor(LMathFloor* instr) { - XMMRegister xmm_scratch = xmm0; + XMMRegister xmm_scratch = double_scratch0(); Register output_reg = ToRegister(instr->result()); XMMRegister input_reg = ToDoubleRegister(instr->value()); @@ -3520,7 +3434,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) { __ bind(&negative_sign); // Truncate, then compare and compensate. __ cvttsd2si(output_reg, input_reg); - __ cvtlsi2sd(xmm_scratch, output_reg); + __ Cvtlsi2sd(xmm_scratch, output_reg); __ ucomisd(input_reg, xmm_scratch); __ j(equal, &done, Label::kNear); __ subl(output_reg, Immediate(1)); @@ -3532,7 +3446,7 @@ void LCodeGen::DoMathFloor(LMathFloor* instr) { void LCodeGen::DoMathRound(LMathRound* instr) { - const XMMRegister xmm_scratch = xmm0; + const XMMRegister xmm_scratch = double_scratch0(); Register output_reg = ToRegister(instr->result()); XMMRegister input_reg = ToDoubleRegister(instr->value()); static int64_t one_half = V8_INT64_C(0x3FE0000000000000); // 0.5 @@ -3569,7 +3483,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) { __ RecordComment("D2I conversion overflow"); DeoptimizeIf(equal, instr->environment()); - __ cvtlsi2sd(xmm_scratch, output_reg); + __ Cvtlsi2sd(xmm_scratch, output_reg); __ ucomisd(input_reg, xmm_scratch); __ j(equal, &restore, Label::kNear); __ subl(output_reg, Immediate(1)); @@ -3600,7 +3514,7 @@ void LCodeGen::DoMathSqrt(LMathSqrt* instr) { void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) { - XMMRegister xmm_scratch = xmm0; + XMMRegister xmm_scratch = double_scratch0(); XMMRegister input_reg = ToDoubleRegister(instr->value()); ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); @@ -3717,8 +3631,7 @@ void LCodeGen::DoRandom(LRandom* instr) { // by computing: // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). XMMRegister result = ToDoubleRegister(instr->result()); - // We use xmm0 as fixed scratch register here. - XMMRegister scratch4 = xmm0; + XMMRegister scratch4 = double_scratch0(); __ movq(scratch3, V8_INT64_C(0x4130000000000000), RelocInfo::NONE64); // 1.0 x 2^20 as double __ movq(scratch4, scratch3); @@ -3731,18 +3644,44 @@ void LCodeGen::DoRandom(LRandom* instr) { void LCodeGen::DoMathExp(LMathExp* instr) { XMMRegister input = ToDoubleRegister(instr->value()); XMMRegister result = ToDoubleRegister(instr->result()); + XMMRegister temp0 = double_scratch0(); Register temp1 = ToRegister(instr->temp1()); Register temp2 = ToRegister(instr->temp2()); - MathExpGenerator::EmitMathExp(masm(), input, result, xmm0, temp1, temp2); + MathExpGenerator::EmitMathExp(masm(), input, result, temp0, temp1, temp2); } void LCodeGen::DoMathLog(LMathLog* instr) { - ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); - TranscendentalCacheStub stub(TranscendentalCache::LOG, - TranscendentalCacheStub::UNTAGGED); - CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); + ASSERT(instr->value()->Equals(instr->result())); + XMMRegister input_reg = ToDoubleRegister(instr->value()); + XMMRegister xmm_scratch = double_scratch0(); + Label positive, done, zero; + __ xorps(xmm_scratch, xmm_scratch); + __ ucomisd(input_reg, xmm_scratch); + __ j(above, &positive, Label::kNear); + __ j(equal, &zero, Label::kNear); + ExternalReference nan = + ExternalReference::address_of_canonical_non_hole_nan(); + Operand nan_operand = masm()->ExternalOperand(nan); + __ movsd(input_reg, nan_operand); + __ jmp(&done, Label::kNear); + __ bind(&zero); + ExternalReference ninf = + ExternalReference::address_of_negative_infinity(); + Operand ninf_operand = masm()->ExternalOperand(ninf); + __ movsd(input_reg, ninf_operand); + __ jmp(&done, Label::kNear); + __ bind(&positive); + __ fldln2(); + __ subq(rsp, Immediate(kDoubleSize)); + __ movsd(Operand(rsp, 0), input_reg); + __ fld_d(Operand(rsp, 0)); + __ fyl2x(); + __ fstp_d(Operand(rsp, 0)); + __ movsd(input_reg, Operand(rsp, 0)); + __ addq(rsp, Immediate(kDoubleSize)); + __ bind(&done); } @@ -3777,7 +3716,6 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { Handle<JSFunction> known_function = instr->hydrogen()->known_function(); if (known_function.is_null()) { LPointerMap* pointers = instr->pointer_map(); - RecordPosition(pointers->position()); SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); ParameterCount count(instr->arity()); __ InvokeFunction(rdi, count, CALL_FUNCTION, generator, CALL_AS_METHOD); @@ -3910,7 +3848,7 @@ void LCodeGen::DoCallNewArray(LCallNewArray* instr) { void LCodeGen::DoCallRuntime(LCallRuntime* instr) { - CallRuntime(instr->function(), instr->arity(), instr); + CallRuntime(instr->function(), instr->arity(), instr, instr->save_doubles()); } @@ -3940,11 +3878,12 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { Register value = ToRegister(instr->value()); if (instr->object()->IsConstantOperand()) { ASSERT(value.is(rax)); + ASSERT(!access.representation().IsSpecialization()); LConstantOperand* object = LConstantOperand::cast(instr->object()); __ store_rax(ToExternalReference(object)); } else { Register object = ToRegister(instr->object()); - __ movq(MemOperand(object, offset), value); + __ Store(MemOperand(object, offset), value, representation); } return; } @@ -4013,15 +3952,16 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { if (instr->value()->IsConstantOperand()) { LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); if (operand_value->IsRegister()) { - __ movq(FieldOperand(write_register, offset), - ToRegister(operand_value)); + Register value = ToRegister(operand_value); + __ Store(FieldOperand(write_register, offset), value, representation); } else { Handle<Object> handle_value = ToHandle(operand_value); ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); __ Move(FieldOperand(write_register, offset), handle_value); } } else { - __ movq(FieldOperand(write_register, offset), ToRegister(instr->value())); + Register value = ToRegister(instr->value()); + __ Store(FieldOperand(write_register, offset), value, representation); } if (instr->hydrogen()->NeedsWriteBarrier()) { @@ -4325,8 +4265,10 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { Register object = ToRegister(instr->object()); Register temp = ToRegister(instr->temp()); - __ TestJSArrayForAllocationMemento(object, temp); + Label no_memento_found; + __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); DeoptimizeIf(equal, instr->environment()); + __ bind(&no_memento_found); } @@ -4449,9 +4391,9 @@ void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { LOperand* output = instr->result(); ASSERT(output->IsDoubleRegister()); if (input->IsRegister()) { - __ cvtlsi2sd(ToDoubleRegister(output), ToRegister(input)); + __ Cvtlsi2sd(ToDoubleRegister(output), ToRegister(input)); } else { - __ cvtlsi2sd(ToDoubleRegister(output), ToOperand(input)); + __ Cvtlsi2sd(ToDoubleRegister(output), ToOperand(input)); } } @@ -4479,6 +4421,22 @@ void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { } +void LCodeGen::DoUint32ToSmi(LUint32ToSmi* instr) { + LOperand* input = instr->value(); + ASSERT(input->IsRegister()); + LOperand* output = instr->result(); + if (!instr->hydrogen()->value()->HasRange() || + !instr->hydrogen()->value()->range()->IsInSmiRange() || + instr->hydrogen()->value()->range()->upper() == kMaxInt) { + // The Range class can't express upper bounds in the (kMaxInt, kMaxUint32] + // interval, so we treat kMaxInt as a sentinel for this entire interval. + __ testl(ToRegister(input), Immediate(0x80000000)); + DeoptimizeIf(not_zero, instr->environment()); + } + __ Integer32ToSmi(ToRegister(output), ToRegister(input)); +} + + void LCodeGen::DoNumberTagI(LNumberTagI* instr) { LOperand* input = instr->value(); ASSERT(input->IsRegister() && input->Equals(instr->result())); @@ -4517,15 +4475,17 @@ void LCodeGen::DoDeferredNumberTagU(LNumberTagU* instr) { Label slow; Register reg = ToRegister(instr->value()); Register tmp = reg.is(rax) ? rcx : rax; + XMMRegister temp_xmm = ToDoubleRegister(instr->temp()); // Preserve the value of all registers. PushSafepointRegistersScope scope(this); Label done; - // Load value into xmm1 which will be preserved across potential call to + // Load value into temp_xmm which will be preserved across potential call to // runtime (MacroAssembler::EnterExitFrameEpilogue preserves only allocatable // XMM registers on x64). - __ LoadUint32(xmm1, reg, xmm0); + XMMRegister xmm_scratch = double_scratch0(); + __ LoadUint32(temp_xmm, reg, xmm_scratch); if (FLAG_inline_new) { __ AllocateHeapNumber(reg, tmp, &slow); @@ -4543,10 +4503,10 @@ void LCodeGen::DoDeferredNumberTagU(LNumberTagU* instr) { CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); if (!reg.is(rax)) __ movq(reg, rax); - // Done. Put the value in xmm1 into the value of the allocated heap + // Done. Put the value in temp_xmm into the value of the allocated heap // number. __ bind(&done); - __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), xmm1); + __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), temp_xmm); __ StoreToSafepointRegisterSlot(reg, reg); } @@ -4623,7 +4583,7 @@ void LCodeGen::EmitNumberUntagD(Register input_reg, bool deoptimize_on_minus_zero, LEnvironment* env, NumberUntagDMode mode) { - Label load_smi, done; + Label convert, load_smi, done; if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { // Smi check. @@ -4632,27 +4592,19 @@ void LCodeGen::EmitNumberUntagD(Register input_reg, // Heap number map check. __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), Heap::kHeapNumberMapRootIndex); - if (!can_convert_undefined_to_nan) { - DeoptimizeIf(not_equal, env); - } else { - Label heap_number, convert; - __ j(equal, &heap_number, Label::kNear); - // Convert undefined (and hole) to NaN. Compute NaN as 0/0. - __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); - DeoptimizeIf(not_equal, env); - - __ bind(&convert); - __ xorps(result_reg, result_reg); - __ divsd(result_reg, result_reg); - __ jmp(&done, Label::kNear); + // On x64 it is safe to load at heap number offset before evaluating the map + // check, since all heap objects are at least two words long. + __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); - __ bind(&heap_number); + if (can_convert_undefined_to_nan) { + __ j(not_equal, &convert); + } else { + DeoptimizeIf(not_equal, env); } - // Heap number to XMM conversion. - __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); + if (deoptimize_on_minus_zero) { - XMMRegister xmm_scratch = xmm0; + XMMRegister xmm_scratch = double_scratch0(); __ xorps(xmm_scratch, xmm_scratch); __ ucomisd(xmm_scratch, result_reg); __ j(not_equal, &done, Label::kNear); @@ -4661,6 +4613,18 @@ void LCodeGen::EmitNumberUntagD(Register input_reg, DeoptimizeIf(not_zero, env); } __ jmp(&done, Label::kNear); + + if (can_convert_undefined_to_nan) { + __ bind(&convert); + + // Convert undefined (and hole) to NaN. Compute NaN as 0/0. + __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); + DeoptimizeIf(not_equal, env); + + __ xorps(result_reg, result_reg); + __ divsd(result_reg, result_reg); + __ jmp(&done, Label::kNear); + } } else { ASSERT(mode == NUMBER_CANDIDATE_IS_SMI); } @@ -4668,30 +4632,44 @@ void LCodeGen::EmitNumberUntagD(Register input_reg, // Smi to XMM conversion __ bind(&load_smi); __ SmiToInteger32(kScratchRegister, input_reg); - __ cvtlsi2sd(result_reg, kScratchRegister); + __ Cvtlsi2sd(result_reg, kScratchRegister); __ bind(&done); } void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) { - Label heap_number; Register input_reg = ToRegister(instr->value()); - if (instr->truncating()) { + Label no_heap_number, check_bools, check_false; + // Heap number map check. __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), Heap::kHeapNumberMapRootIndex); - __ j(equal, &heap_number, Label::kNear); - // Check for undefined. Undefined is converted to zero for truncating - // conversions. + __ j(not_equal, &no_heap_number, Label::kNear); + __ TruncateHeapNumberToI(input_reg, input_reg); + __ jmp(done); + + __ bind(&no_heap_number); + // Check for Oddballs. Undefined/False is converted to zero and True to one + // for truncating conversions. __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); - DeoptimizeIf(not_equal, instr->environment()); + __ j(not_equal, &check_bools, Label::kNear); __ Set(input_reg, 0); __ jmp(done); - __ bind(&heap_number); - __ TruncateHeapNumberToI(input_reg, input_reg); + __ bind(&check_bools); + __ CompareRoot(input_reg, Heap::kTrueValueRootIndex); + __ j(not_equal, &check_false, Label::kNear); + __ Set(input_reg, 1); + __ jmp(done); + + __ bind(&check_false); + __ CompareRoot(input_reg, Heap::kFalseValueRootIndex); + __ RecordComment("Deferred TaggedToI: cannot truncate"); + DeoptimizeIf(not_equal, instr->environment()); + __ Set(input_reg, 0); + __ jmp(done); } else { Label bailout; XMMRegister xmm_temp = ToDoubleRegister(instr->temp()); @@ -4721,12 +4699,16 @@ void LCodeGen::DoTaggedToI(LTaggedToI* instr) { LOperand* input = instr->value(); ASSERT(input->IsRegister()); ASSERT(input->Equals(instr->result())); - Register input_reg = ToRegister(input); - DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr); - __ JumpIfNotSmi(input_reg, deferred->entry()); - __ SmiToInteger32(input_reg, input_reg); - __ bind(deferred->exit()); + + if (instr->hydrogen()->value()->representation().IsSmi()) { + __ SmiToInteger32(input_reg, input_reg); + } else { + DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr); + __ JumpIfNotSmi(input_reg, deferred->entry()); + __ SmiToInteger32(input_reg, input_reg); + __ bind(deferred->exit()); + } } @@ -4764,7 +4746,8 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) { __ TruncateDoubleToI(result_reg, input_reg); } else { Label bailout, done; - __ DoubleToI(result_reg, input_reg, xmm0, + XMMRegister xmm_scratch = double_scratch0(); + __ DoubleToI(result_reg, input_reg, xmm_scratch, instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); __ jmp(&done, Label::kNear); @@ -4785,7 +4768,8 @@ void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { Register result_reg = ToRegister(result); Label bailout, done; - __ DoubleToI(result_reg, input_reg, xmm0, + XMMRegister xmm_scratch = double_scratch0(); + __ DoubleToI(result_reg, input_reg, xmm_scratch, instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); __ jmp(&done, Label::kNear); @@ -4862,8 +4846,7 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { void LCodeGen::DoCheckValue(LCheckValue* instr) { Register reg = ToRegister(instr->value()); - Handle<HeapObject> object = instr->hydrogen()->object(); - __ CmpHeapObject(reg, object); + __ Cmp(reg, instr->hydrogen()->object().handle()); DeoptimizeIf(not_equal, instr->environment()); } @@ -4903,22 +4886,21 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) { ASSERT(input->IsRegister()); Register reg = ToRegister(input); - SmallMapList* map_set = instr->hydrogen()->map_set(); - DeferredCheckMaps* deferred = NULL; if (instr->hydrogen()->has_migration_target()) { deferred = new(zone()) DeferredCheckMaps(this, instr, reg); __ bind(deferred->check_maps()); } + UniqueSet<Map> map_set = instr->hydrogen()->map_set(); Label success; - for (int i = 0; i < map_set->length() - 1; i++) { - Handle<Map> map = map_set->at(i); + for (int i = 0; i < map_set.size() - 1; i++) { + Handle<Map> map = map_set.at(i).handle(); __ CompareMap(reg, map, &success); __ j(equal, &success); } - Handle<Map> map = map_set->last(); + Handle<Map> map = map_set.at(map_set.size() - 1).handle(); __ CompareMap(reg, map, &success); if (instr->hydrogen()->has_migration_target()) { __ j(not_equal, deferred->entry()); @@ -4932,8 +4914,9 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) { void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); + XMMRegister xmm_scratch = double_scratch0(); Register result_reg = ToRegister(instr->result()); - __ ClampDoubleToUint8(value_reg, xmm0, result_reg); + __ ClampDoubleToUint8(value_reg, xmm_scratch, result_reg); } @@ -4948,6 +4931,7 @@ void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { ASSERT(instr->unclamped()->Equals(instr->result())); Register input_reg = ToRegister(instr->unclamped()); XMMRegister temp_xmm_reg = ToDoubleRegister(instr->temp_xmm()); + XMMRegister xmm_scratch = double_scratch0(); Label is_smi, done, heap_number; __ JumpIfSmi(input_reg, &is_smi); @@ -4966,8 +4950,8 @@ void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { // Heap number __ bind(&heap_number); - __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); - __ ClampDoubleToUint8(xmm0, temp_xmm_reg, input_reg); + __ movsd(xmm_scratch, FieldOperand(input_reg, HeapNumber::kValueOffset)); + __ ClampDoubleToUint8(xmm_scratch, temp_xmm_reg, input_reg); __ jmp(&done, Label::kNear); // smi @@ -5089,7 +5073,7 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { // rax = regexp literal clone. int literal_offset = FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index()); - __ LoadHeapObject(rcx, instr->hydrogen()->literals()); + __ Move(rcx, instr->hydrogen()->literals()); __ movq(rbx, FieldOperand(rcx, literal_offset)); __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); __ j(not_equal, &materialized, Label::kNear); @@ -5160,13 +5144,7 @@ void LCodeGen::DoTypeof(LTypeof* instr) { void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { ASSERT(!operand->IsDoubleRegister()); if (operand->IsConstantOperand()) { - Handle<Object> object = ToHandle(LConstantOperand::cast(operand)); - AllowDeferredHandleDereference smi_check; - if (object->IsSmi()) { - __ Push(Handle<Smi>::cast(object)); - } else { - __ PushHeapObject(Handle<HeapObject>::cast(object)); - } + __ Push(ToHandle(LConstantOperand::cast(operand))); } else if (operand->IsRegister()) { __ push(ToRegister(operand)); } else { @@ -5280,7 +5258,7 @@ void LCodeGen::EmitIsConstructCall(Register temp) { __ Cmp(Operand(temp, StandardFrameConstants::kContextOffset), Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); __ j(not_equal, &check_frame_marker, Label::kNear); - __ movq(temp, Operand(rax, StandardFrameConstants::kCallerFPOffset)); + __ movq(temp, Operand(temp, StandardFrameConstants::kCallerFPOffset)); // Check the marker in the calling frame. __ bind(&check_frame_marker); |