| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); | 136 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); |
| 137 __ movq(args.GetReceiverOperand(), kScratchRegister); | 137 __ movq(args.GetReceiverOperand(), kScratchRegister); |
| 138 __ bind(&ok); | 138 __ bind(&ok); |
| 139 } | 139 } |
| 140 } | 140 } |
| 141 | 141 |
| 142 info()->set_prologue_offset(masm_->pc_offset()); | 142 info()->set_prologue_offset(masm_->pc_offset()); |
| 143 if (NeedsEagerFrame()) { | 143 if (NeedsEagerFrame()) { |
| 144 ASSERT(!frame_is_built_); | 144 ASSERT(!frame_is_built_); |
| 145 frame_is_built_ = true; | 145 frame_is_built_ = true; |
| 146 __ push(rbp); // Caller's frame pointer. | 146 __ Prologue(info()->IsStub() ? BUILD_STUB_FRAME : BUILD_FUNCTION_FRAME); |
| 147 __ movq(rbp, rsp); | |
| 148 __ push(rsi); // Callee's context. | |
| 149 if (info()->IsStub()) { | |
| 150 __ Push(Smi::FromInt(StackFrame::STUB)); | |
| 151 } else { | |
| 152 __ push(rdi); // Callee's JS function. | |
| 153 } | |
| 154 info()->AddNoFrameRange(0, masm_->pc_offset()); | 147 info()->AddNoFrameRange(0, masm_->pc_offset()); |
| 155 } | 148 } |
| 156 | 149 |
| 157 // Reserve space for the stack slots needed by the code. | 150 // Reserve space for the stack slots needed by the code. |
| 158 int slots = GetStackSlotCount(); | 151 int slots = GetStackSlotCount(); |
| 159 if (slots > 0) { | 152 if (slots > 0) { |
| 160 if (FLAG_debug_code) { | 153 if (FLAG_debug_code) { |
| 161 __ subq(rsp, Immediate(slots * kPointerSize)); | 154 __ subq(rsp, Immediate(slots * kPointerSize)); |
| 162 #ifdef _MSC_VER | 155 #ifdef _MSC_VER |
| 163 MakeSureStackPagesMapped(slots * kPointerSize); | 156 MakeSureStackPagesMapped(slots * kPointerSize); |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 return !is_aborted(); | 285 return !is_aborted(); |
| 293 } | 286 } |
| 294 | 287 |
| 295 | 288 |
| 296 bool LCodeGen::GenerateDeferredCode() { | 289 bool LCodeGen::GenerateDeferredCode() { |
| 297 ASSERT(is_generating()); | 290 ASSERT(is_generating()); |
| 298 if (deferred_.length() > 0) { | 291 if (deferred_.length() > 0) { |
| 299 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { | 292 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { |
| 300 LDeferredCode* code = deferred_[i]; | 293 LDeferredCode* code = deferred_[i]; |
| 301 | 294 |
| 302 int pos = instructions_->at(code->instruction_index())->position(); | 295 HValue* value = |
| 303 RecordAndUpdatePosition(pos); | 296 instructions_->at(code->instruction_index())->hydrogen_value(); |
| 297 RecordAndWritePosition(value->position()); |
| 304 | 298 |
| 305 Comment(";;; <@%d,#%d> " | 299 Comment(";;; <@%d,#%d> " |
| 306 "-------------------- Deferred %s --------------------", | 300 "-------------------- Deferred %s --------------------", |
| 307 code->instruction_index(), | 301 code->instruction_index(), |
| 308 code->instr()->hydrogen_value()->id(), | 302 code->instr()->hydrogen_value()->id(), |
| 309 code->instr()->Mnemonic()); | 303 code->instr()->Mnemonic()); |
| 310 __ bind(code->entry()); | 304 __ bind(code->entry()); |
| 311 if (NeedsDeferredFrame()) { | 305 if (NeedsDeferredFrame()) { |
| 312 Comment(";;; Build frame"); | 306 Comment(";;; Build frame"); |
| 313 ASSERT(!frame_is_built_); | 307 ASSERT(!frame_is_built_); |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 556 } | 550 } |
| 557 | 551 |
| 558 | 552 |
| 559 void LCodeGen::CallCodeGeneric(Handle<Code> code, | 553 void LCodeGen::CallCodeGeneric(Handle<Code> code, |
| 560 RelocInfo::Mode mode, | 554 RelocInfo::Mode mode, |
| 561 LInstruction* instr, | 555 LInstruction* instr, |
| 562 SafepointMode safepoint_mode, | 556 SafepointMode safepoint_mode, |
| 563 int argc) { | 557 int argc) { |
| 564 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size() - masm()->CallSize(code)); | 558 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size() - masm()->CallSize(code)); |
| 565 ASSERT(instr != NULL); | 559 ASSERT(instr != NULL); |
| 566 LPointerMap* pointers = instr->pointer_map(); | |
| 567 RecordPosition(pointers->position()); | |
| 568 __ call(code, mode); | 560 __ call(code, mode); |
| 569 RecordSafepointWithLazyDeopt(instr, safepoint_mode, argc); | 561 RecordSafepointWithLazyDeopt(instr, safepoint_mode, argc); |
| 570 | 562 |
| 571 // Signal that we don't inline smi code before these stubs in the | 563 // Signal that we don't inline smi code before these stubs in the |
| 572 // optimizing code generator. | 564 // optimizing code generator. |
| 573 if (code->kind() == Code::BINARY_OP_IC || | 565 if (code->kind() == Code::BINARY_OP_IC || |
| 574 code->kind() == Code::COMPARE_IC) { | 566 code->kind() == Code::COMPARE_IC) { |
| 575 __ nop(); | 567 __ nop(); |
| 576 } | 568 } |
| 577 } | 569 } |
| 578 | 570 |
| 579 | 571 |
| 580 void LCodeGen::CallCode(Handle<Code> code, | 572 void LCodeGen::CallCode(Handle<Code> code, |
| 581 RelocInfo::Mode mode, | 573 RelocInfo::Mode mode, |
| 582 LInstruction* instr) { | 574 LInstruction* instr) { |
| 583 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT, 0); | 575 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT, 0); |
| 584 } | 576 } |
| 585 | 577 |
| 586 | 578 |
| 587 void LCodeGen::CallRuntime(const Runtime::Function* function, | 579 void LCodeGen::CallRuntime(const Runtime::Function* function, |
| 588 int num_arguments, | 580 int num_arguments, |
| 589 LInstruction* instr, | 581 LInstruction* instr, |
| 590 SaveFPRegsMode save_doubles) { | 582 SaveFPRegsMode save_doubles) { |
| 591 ASSERT(instr != NULL); | 583 ASSERT(instr != NULL); |
| 592 ASSERT(instr->HasPointerMap()); | 584 ASSERT(instr->HasPointerMap()); |
| 593 LPointerMap* pointers = instr->pointer_map(); | |
| 594 RecordPosition(pointers->position()); | |
| 595 | 585 |
| 596 __ CallRuntime(function, num_arguments, save_doubles); | 586 __ CallRuntime(function, num_arguments, save_doubles); |
| 597 | 587 |
| 598 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0); | 588 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0); |
| 599 } | 589 } |
| 600 | 590 |
| 601 | 591 |
| 602 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, | 592 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, |
| 603 int argc, | 593 int argc, |
| 604 LInstruction* instr) { | 594 LInstruction* instr) { |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 833 } | 823 } |
| 834 | 824 |
| 835 | 825 |
| 836 void LCodeGen::RecordSafepoint(LPointerMap* pointers, | 826 void LCodeGen::RecordSafepoint(LPointerMap* pointers, |
| 837 Safepoint::DeoptMode deopt_mode) { | 827 Safepoint::DeoptMode deopt_mode) { |
| 838 RecordSafepoint(pointers, Safepoint::kSimple, 0, deopt_mode); | 828 RecordSafepoint(pointers, Safepoint::kSimple, 0, deopt_mode); |
| 839 } | 829 } |
| 840 | 830 |
| 841 | 831 |
| 842 void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) { | 832 void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) { |
| 843 LPointerMap empty_pointers(RelocInfo::kNoPosition, zone()); | 833 LPointerMap empty_pointers(zone()); |
| 844 RecordSafepoint(&empty_pointers, deopt_mode); | 834 RecordSafepoint(&empty_pointers, deopt_mode); |
| 845 } | 835 } |
| 846 | 836 |
| 847 | 837 |
| 848 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, | 838 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, |
| 849 int arguments, | 839 int arguments, |
| 850 Safepoint::DeoptMode deopt_mode) { | 840 Safepoint::DeoptMode deopt_mode) { |
| 851 RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, deopt_mode); | 841 RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, deopt_mode); |
| 852 } | 842 } |
| 853 | 843 |
| 854 | 844 |
| 855 void LCodeGen::RecordPosition(int position) { | 845 void LCodeGen::RecordAndWritePosition(int position) { |
| 856 if (position == RelocInfo::kNoPosition) return; | 846 if (position == RelocInfo::kNoPosition) return; |
| 857 masm()->positions_recorder()->RecordPosition(position); | 847 masm()->positions_recorder()->RecordPosition(position); |
| 848 masm()->positions_recorder()->WriteRecordedPositions(); |
| 858 } | 849 } |
| 859 | 850 |
| 860 | 851 |
| 861 void LCodeGen::RecordAndUpdatePosition(int position) { | |
| 862 if (position >= 0 && position != old_position_) { | |
| 863 masm()->positions_recorder()->RecordPosition(position); | |
| 864 old_position_ = position; | |
| 865 } | |
| 866 } | |
| 867 | |
| 868 | |
| 869 static const char* LabelType(LLabel* label) { | 852 static const char* LabelType(LLabel* label) { |
| 870 if (label->is_loop_header()) return " (loop header)"; | 853 if (label->is_loop_header()) return " (loop header)"; |
| 871 if (label->is_osr_entry()) return " (OSR entry)"; | 854 if (label->is_osr_entry()) return " (OSR entry)"; |
| 872 return ""; | 855 return ""; |
| 873 } | 856 } |
| 874 | 857 |
| 875 | 858 |
| 876 void LCodeGen::DoLabel(LLabel* label) { | 859 void LCodeGen::DoLabel(LLabel* label) { |
| 877 Comment(";;; <@%d,#%d> -------------------- B%d%s --------------------", | 860 Comment(";;; <@%d,#%d> -------------------- B%d%s --------------------", |
| 878 current_instruction_, | 861 current_instruction_, |
| (...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1559 } | 1542 } |
| 1560 | 1543 |
| 1561 | 1544 |
| 1562 void LCodeGen::DoConstantE(LConstantE* instr) { | 1545 void LCodeGen::DoConstantE(LConstantE* instr) { |
| 1563 __ LoadAddress(ToRegister(instr->result()), instr->value()); | 1546 __ LoadAddress(ToRegister(instr->result()), instr->value()); |
| 1564 } | 1547 } |
| 1565 | 1548 |
| 1566 | 1549 |
| 1567 void LCodeGen::DoConstantT(LConstantT* instr) { | 1550 void LCodeGen::DoConstantT(LConstantT* instr) { |
| 1568 Handle<Object> value = instr->value(isolate()); | 1551 Handle<Object> value = instr->value(isolate()); |
| 1569 AllowDeferredHandleDereference smi_check; | 1552 __ Move(ToRegister(instr->result()), value); |
| 1570 __ LoadObject(ToRegister(instr->result()), value); | |
| 1571 } | 1553 } |
| 1572 | 1554 |
| 1573 | 1555 |
| 1574 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { | 1556 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { |
| 1575 Register result = ToRegister(instr->result()); | 1557 Register result = ToRegister(instr->result()); |
| 1576 Register map = ToRegister(instr->value()); | 1558 Register map = ToRegister(instr->value()); |
| 1577 __ EnumLength(result, map); | 1559 __ EnumLength(result, map); |
| 1578 } | 1560 } |
| 1579 | 1561 |
| 1580 | 1562 |
| (...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2041 } | 2023 } |
| 2042 | 2024 |
| 2043 | 2025 |
| 2044 inline Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { | 2026 inline Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { |
| 2045 Condition cond = no_condition; | 2027 Condition cond = no_condition; |
| 2046 switch (op) { | 2028 switch (op) { |
| 2047 case Token::EQ: | 2029 case Token::EQ: |
| 2048 case Token::EQ_STRICT: | 2030 case Token::EQ_STRICT: |
| 2049 cond = equal; | 2031 cond = equal; |
| 2050 break; | 2032 break; |
| 2033 case Token::NE: |
| 2034 case Token::NE_STRICT: |
| 2035 cond = not_equal; |
| 2036 break; |
| 2051 case Token::LT: | 2037 case Token::LT: |
| 2052 cond = is_unsigned ? below : less; | 2038 cond = is_unsigned ? below : less; |
| 2053 break; | 2039 break; |
| 2054 case Token::GT: | 2040 case Token::GT: |
| 2055 cond = is_unsigned ? above : greater; | 2041 cond = is_unsigned ? above : greater; |
| 2056 break; | 2042 break; |
| 2057 case Token::LTE: | 2043 case Token::LTE: |
| 2058 cond = is_unsigned ? below_equal : less_equal; | 2044 cond = is_unsigned ? below_equal : less_equal; |
| 2059 break; | 2045 break; |
| 2060 case Token::GTE: | 2046 case Token::GTE: |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2128 EmitBranch(instr, cc); | 2114 EmitBranch(instr, cc); |
| 2129 } | 2115 } |
| 2130 } | 2116 } |
| 2131 | 2117 |
| 2132 | 2118 |
| 2133 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { | 2119 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { |
| 2134 Register left = ToRegister(instr->left()); | 2120 Register left = ToRegister(instr->left()); |
| 2135 | 2121 |
| 2136 if (instr->right()->IsConstantOperand()) { | 2122 if (instr->right()->IsConstantOperand()) { |
| 2137 Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right())); | 2123 Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right())); |
| 2138 __ CmpObject(left, right); | 2124 __ Cmp(left, right); |
| 2139 } else { | 2125 } else { |
| 2140 Register right = ToRegister(instr->right()); | 2126 Register right = ToRegister(instr->right()); |
| 2141 __ cmpq(left, right); | 2127 __ cmpq(left, right); |
| 2142 } | 2128 } |
| 2143 EmitBranch(instr, equal); | 2129 EmitBranch(instr, equal); |
| 2144 } | 2130 } |
| 2145 | 2131 |
| 2146 | 2132 |
| 2147 void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) { | 2133 void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) { |
| 2148 if (instr->hydrogen()->representation().IsTagged()) { | 2134 if (instr->hydrogen()->representation().IsTagged()) { |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2496 | 2482 |
| 2497 void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, | 2483 void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, |
| 2498 Label* map_check) { | 2484 Label* map_check) { |
| 2499 { | 2485 { |
| 2500 PushSafepointRegistersScope scope(this); | 2486 PushSafepointRegistersScope scope(this); |
| 2501 InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>( | 2487 InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>( |
| 2502 InstanceofStub::kNoFlags | InstanceofStub::kCallSiteInlineCheck); | 2488 InstanceofStub::kNoFlags | InstanceofStub::kCallSiteInlineCheck); |
| 2503 InstanceofStub stub(flags); | 2489 InstanceofStub stub(flags); |
| 2504 | 2490 |
| 2505 __ push(ToRegister(instr->value())); | 2491 __ push(ToRegister(instr->value())); |
| 2506 __ PushHeapObject(instr->function()); | 2492 __ Push(instr->function()); |
| 2507 | 2493 |
| 2508 static const int kAdditionalDelta = 10; | 2494 static const int kAdditionalDelta = 10; |
| 2509 int delta = | 2495 int delta = |
| 2510 masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; | 2496 masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; |
| 2511 ASSERT(delta >= 0); | 2497 ASSERT(delta >= 0); |
| 2512 __ push_imm32(delta); | 2498 __ push_imm32(delta); |
| 2513 | 2499 |
| 2514 // We are pushing three values on the stack but recording a | 2500 // We are pushing three values on the stack but recording a |
| 2515 // safepoint with two arguments because stub is going to | 2501 // safepoint with two arguments because stub is going to |
| 2516 // remove the third argument from the stack before jumping | 2502 // remove the third argument from the stack before jumping |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2532 Label done; | 2518 Label done; |
| 2533 __ j(not_zero, &load_false); | 2519 __ j(not_zero, &load_false); |
| 2534 __ LoadRoot(rax, Heap::kTrueValueRootIndex); | 2520 __ LoadRoot(rax, Heap::kTrueValueRootIndex); |
| 2535 __ jmp(&done); | 2521 __ jmp(&done); |
| 2536 __ bind(&load_false); | 2522 __ bind(&load_false); |
| 2537 __ LoadRoot(rax, Heap::kFalseValueRootIndex); | 2523 __ LoadRoot(rax, Heap::kFalseValueRootIndex); |
| 2538 __ bind(&done); | 2524 __ bind(&done); |
| 2539 } | 2525 } |
| 2540 | 2526 |
| 2541 | 2527 |
| 2542 void LCodeGen::DoInstanceSize(LInstanceSize* instr) { | |
| 2543 Register object = ToRegister(instr->object()); | |
| 2544 Register result = ToRegister(instr->result()); | |
| 2545 __ movq(result, FieldOperand(object, HeapObject::kMapOffset)); | |
| 2546 __ movzxbq(result, FieldOperand(result, Map::kInstanceSizeOffset)); | |
| 2547 } | |
| 2548 | |
| 2549 | |
| 2550 void LCodeGen::DoCmpT(LCmpT* instr) { | 2528 void LCodeGen::DoCmpT(LCmpT* instr) { |
| 2551 Token::Value op = instr->op(); | 2529 Token::Value op = instr->op(); |
| 2552 | 2530 |
| 2553 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 2531 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
| 2554 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2532 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2555 | 2533 |
| 2556 Condition condition = TokenToCondition(op, false); | 2534 Condition condition = TokenToCondition(op, false); |
| 2557 Label true_value, done; | 2535 Label true_value, done; |
| 2558 __ testq(rax, rax); | 2536 __ testq(rax, rax); |
| 2559 __ j(condition, &true_value, Label::kNear); | 2537 __ j(condition, &true_value, Label::kNear); |
| (...skipping 613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3173 StackArgumentsAccessor args(elements, length, | 3151 StackArgumentsAccessor args(elements, length, |
| 3174 ARGUMENTS_DONT_CONTAIN_RECEIVER); | 3152 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 3175 __ push(args.GetArgumentOperand(0)); | 3153 __ push(args.GetArgumentOperand(0)); |
| 3176 __ decl(length); | 3154 __ decl(length); |
| 3177 __ j(not_zero, &loop); | 3155 __ j(not_zero, &loop); |
| 3178 | 3156 |
| 3179 // Invoke the function. | 3157 // Invoke the function. |
| 3180 __ bind(&invoke); | 3158 __ bind(&invoke); |
| 3181 ASSERT(instr->HasPointerMap()); | 3159 ASSERT(instr->HasPointerMap()); |
| 3182 LPointerMap* pointers = instr->pointer_map(); | 3160 LPointerMap* pointers = instr->pointer_map(); |
| 3183 RecordPosition(pointers->position()); | |
| 3184 SafepointGenerator safepoint_generator( | 3161 SafepointGenerator safepoint_generator( |
| 3185 this, pointers, Safepoint::kLazyDeopt); | 3162 this, pointers, Safepoint::kLazyDeopt); |
| 3186 ParameterCount actual(rax); | 3163 ParameterCount actual(rax); |
| 3187 __ InvokeFunction(function, actual, CALL_FUNCTION, | 3164 __ InvokeFunction(function, actual, CALL_FUNCTION, |
| 3188 safepoint_generator, CALL_AS_METHOD); | 3165 safepoint_generator, CALL_AS_METHOD); |
| 3189 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 3166 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 3190 } | 3167 } |
| 3191 | 3168 |
| 3192 | 3169 |
| 3193 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 3170 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 3216 void LCodeGen::DoOuterContext(LOuterContext* instr) { | 3193 void LCodeGen::DoOuterContext(LOuterContext* instr) { |
| 3217 Register context = ToRegister(instr->context()); | 3194 Register context = ToRegister(instr->context()); |
| 3218 Register result = ToRegister(instr->result()); | 3195 Register result = ToRegister(instr->result()); |
| 3219 __ movq(result, | 3196 __ movq(result, |
| 3220 Operand(context, Context::SlotOffset(Context::PREVIOUS_INDEX))); | 3197 Operand(context, Context::SlotOffset(Context::PREVIOUS_INDEX))); |
| 3221 } | 3198 } |
| 3222 | 3199 |
| 3223 | 3200 |
| 3224 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { | 3201 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { |
| 3225 __ push(rsi); // The context is the first argument. | 3202 __ push(rsi); // The context is the first argument. |
| 3226 __ PushHeapObject(instr->hydrogen()->pairs()); | 3203 __ Push(instr->hydrogen()->pairs()); |
| 3227 __ Push(Smi::FromInt(instr->hydrogen()->flags())); | 3204 __ Push(Smi::FromInt(instr->hydrogen()->flags())); |
| 3228 CallRuntime(Runtime::kDeclareGlobals, 3, instr); | 3205 CallRuntime(Runtime::kDeclareGlobals, 3, instr); |
| 3229 } | 3206 } |
| 3230 | 3207 |
| 3231 | 3208 |
| 3232 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { | 3209 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { |
| 3233 Register result = ToRegister(instr->result()); | 3210 Register result = ToRegister(instr->result()); |
| 3234 __ movq(result, GlobalObjectOperand()); | 3211 __ movq(result, GlobalObjectOperand()); |
| 3235 } | 3212 } |
| 3236 | 3213 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3247 int arity, | 3224 int arity, |
| 3248 LInstruction* instr, | 3225 LInstruction* instr, |
| 3249 CallKind call_kind, | 3226 CallKind call_kind, |
| 3250 RDIState rdi_state) { | 3227 RDIState rdi_state) { |
| 3251 bool dont_adapt_arguments = | 3228 bool dont_adapt_arguments = |
| 3252 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; | 3229 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; |
| 3253 bool can_invoke_directly = | 3230 bool can_invoke_directly = |
| 3254 dont_adapt_arguments || formal_parameter_count == arity; | 3231 dont_adapt_arguments || formal_parameter_count == arity; |
| 3255 | 3232 |
| 3256 LPointerMap* pointers = instr->pointer_map(); | 3233 LPointerMap* pointers = instr->pointer_map(); |
| 3257 RecordPosition(pointers->position()); | |
| 3258 | 3234 |
| 3259 if (can_invoke_directly) { | 3235 if (can_invoke_directly) { |
| 3260 if (rdi_state == RDI_UNINITIALIZED) { | 3236 if (rdi_state == RDI_UNINITIALIZED) { |
| 3261 __ LoadHeapObject(rdi, function); | 3237 __ Move(rdi, function); |
| 3262 } | 3238 } |
| 3263 | 3239 |
| 3264 // Change context. | 3240 // Change context. |
| 3265 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | 3241 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
| 3266 | 3242 |
| 3267 // Set rax to arguments count if adaption is not needed. Assumes that rax | 3243 // Set rax to arguments count if adaption is not needed. Assumes that rax |
| 3268 // is available to write to at this point. | 3244 // is available to write to at this point. |
| 3269 if (dont_adapt_arguments) { | 3245 if (dont_adapt_arguments) { |
| 3270 __ Set(rax, arity); | 3246 __ Set(rax, arity); |
| 3271 } | 3247 } |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3332 | 3308 |
| 3333 // Slow case: Call the runtime system to do the number allocation. | 3309 // Slow case: Call the runtime system to do the number allocation. |
| 3334 __ bind(&slow); | 3310 __ bind(&slow); |
| 3335 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 3311 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); |
| 3336 // Set the pointer to the new heap number in tmp. | 3312 // Set the pointer to the new heap number in tmp. |
| 3337 if (!tmp.is(rax)) __ movq(tmp, rax); | 3313 if (!tmp.is(rax)) __ movq(tmp, rax); |
| 3338 // Restore input_reg after call to runtime. | 3314 // Restore input_reg after call to runtime. |
| 3339 __ LoadFromSafepointRegisterSlot(input_reg, input_reg); | 3315 __ LoadFromSafepointRegisterSlot(input_reg, input_reg); |
| 3340 | 3316 |
| 3341 __ bind(&allocated); | 3317 __ bind(&allocated); |
| 3342 __ movq(tmp2, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 3318 __ MoveDouble(tmp2, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 3343 __ shl(tmp2, Immediate(1)); | 3319 __ shl(tmp2, Immediate(1)); |
| 3344 __ shr(tmp2, Immediate(1)); | 3320 __ shr(tmp2, Immediate(1)); |
| 3345 __ movq(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2); | 3321 __ MoveDouble(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2); |
| 3346 __ StoreToSafepointRegisterSlot(input_reg, tmp); | 3322 __ StoreToSafepointRegisterSlot(input_reg, tmp); |
| 3347 | 3323 |
| 3348 __ bind(&done); | 3324 __ bind(&done); |
| 3349 } | 3325 } |
| 3350 | 3326 |
| 3351 | 3327 |
| 3352 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { | 3328 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { |
| 3353 Register input_reg = ToRegister(instr->value()); | 3329 Register input_reg = ToRegister(instr->value()); |
| 3354 __ testl(input_reg, input_reg); | 3330 __ testl(input_reg, input_reg); |
| 3355 Label is_positive; | 3331 Label is_positive; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 3386 }; | 3362 }; |
| 3387 | 3363 |
| 3388 ASSERT(instr->value()->Equals(instr->result())); | 3364 ASSERT(instr->value()->Equals(instr->result())); |
| 3389 Representation r = instr->hydrogen()->value()->representation(); | 3365 Representation r = instr->hydrogen()->value()->representation(); |
| 3390 | 3366 |
| 3391 if (r.IsDouble()) { | 3367 if (r.IsDouble()) { |
| 3392 XMMRegister scratch = double_scratch0(); | 3368 XMMRegister scratch = double_scratch0(); |
| 3393 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3369 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 3394 __ xorps(scratch, scratch); | 3370 __ xorps(scratch, scratch); |
| 3395 __ subsd(scratch, input_reg); | 3371 __ subsd(scratch, input_reg); |
| 3396 __ andpd(input_reg, scratch); | 3372 __ andps(input_reg, scratch); |
| 3397 } else if (r.IsInteger32()) { | 3373 } else if (r.IsInteger32()) { |
| 3398 EmitIntegerMathAbs(instr); | 3374 EmitIntegerMathAbs(instr); |
| 3399 } else if (r.IsSmi()) { | 3375 } else if (r.IsSmi()) { |
| 3400 EmitSmiMathAbs(instr); | 3376 EmitSmiMathAbs(instr); |
| 3401 } else { // Tagged case. | 3377 } else { // Tagged case. |
| 3402 DeferredMathAbsTaggedHeapNumber* deferred = | 3378 DeferredMathAbsTaggedHeapNumber* deferred = |
| 3403 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr); | 3379 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr); |
| 3404 Register input_reg = ToRegister(instr->value()); | 3380 Register input_reg = ToRegister(instr->value()); |
| 3405 // Smi check. | 3381 // Smi check. |
| 3406 __ JumpIfNotSmi(input_reg, deferred->entry()); | 3382 __ JumpIfNotSmi(input_reg, deferred->entry()); |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3670 XMMRegister result = ToDoubleRegister(instr->result()); | 3646 XMMRegister result = ToDoubleRegister(instr->result()); |
| 3671 XMMRegister temp0 = double_scratch0(); | 3647 XMMRegister temp0 = double_scratch0(); |
| 3672 Register temp1 = ToRegister(instr->temp1()); | 3648 Register temp1 = ToRegister(instr->temp1()); |
| 3673 Register temp2 = ToRegister(instr->temp2()); | 3649 Register temp2 = ToRegister(instr->temp2()); |
| 3674 | 3650 |
| 3675 MathExpGenerator::EmitMathExp(masm(), input, result, temp0, temp1, temp2); | 3651 MathExpGenerator::EmitMathExp(masm(), input, result, temp0, temp1, temp2); |
| 3676 } | 3652 } |
| 3677 | 3653 |
| 3678 | 3654 |
| 3679 void LCodeGen::DoMathLog(LMathLog* instr) { | 3655 void LCodeGen::DoMathLog(LMathLog* instr) { |
| 3680 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | 3656 ASSERT(instr->value()->Equals(instr->result())); |
| 3681 TranscendentalCacheStub stub(TranscendentalCache::LOG, | 3657 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 3682 TranscendentalCacheStub::UNTAGGED); | 3658 XMMRegister xmm_scratch = double_scratch0(); |
| 3683 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 3659 Label positive, done, zero; |
| 3660 __ xorps(xmm_scratch, xmm_scratch); |
| 3661 __ ucomisd(input_reg, xmm_scratch); |
| 3662 __ j(above, &positive, Label::kNear); |
| 3663 __ j(equal, &zero, Label::kNear); |
| 3664 ExternalReference nan = |
| 3665 ExternalReference::address_of_canonical_non_hole_nan(); |
| 3666 Operand nan_operand = masm()->ExternalOperand(nan); |
| 3667 __ movsd(input_reg, nan_operand); |
| 3668 __ jmp(&done, Label::kNear); |
| 3669 __ bind(&zero); |
| 3670 ExternalReference ninf = |
| 3671 ExternalReference::address_of_negative_infinity(); |
| 3672 Operand ninf_operand = masm()->ExternalOperand(ninf); |
| 3673 __ movsd(input_reg, ninf_operand); |
| 3674 __ jmp(&done, Label::kNear); |
| 3675 __ bind(&positive); |
| 3676 __ fldln2(); |
| 3677 __ subq(rsp, Immediate(kDoubleSize)); |
| 3678 __ movsd(Operand(rsp, 0), input_reg); |
| 3679 __ fld_d(Operand(rsp, 0)); |
| 3680 __ fyl2x(); |
| 3681 __ fstp_d(Operand(rsp, 0)); |
| 3682 __ movsd(input_reg, Operand(rsp, 0)); |
| 3683 __ addq(rsp, Immediate(kDoubleSize)); |
| 3684 __ bind(&done); |
| 3684 } | 3685 } |
| 3685 | 3686 |
| 3686 | 3687 |
| 3687 void LCodeGen::DoMathTan(LMathTan* instr) { | 3688 void LCodeGen::DoMathTan(LMathTan* instr) { |
| 3688 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | 3689 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
| 3689 TranscendentalCacheStub stub(TranscendentalCache::TAN, | 3690 TranscendentalCacheStub stub(TranscendentalCache::TAN, |
| 3690 TranscendentalCacheStub::UNTAGGED); | 3691 TranscendentalCacheStub::UNTAGGED); |
| 3691 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 3692 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 3692 } | 3693 } |
| 3693 | 3694 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 3708 } | 3709 } |
| 3709 | 3710 |
| 3710 | 3711 |
| 3711 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { | 3712 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
| 3712 ASSERT(ToRegister(instr->function()).is(rdi)); | 3713 ASSERT(ToRegister(instr->function()).is(rdi)); |
| 3713 ASSERT(instr->HasPointerMap()); | 3714 ASSERT(instr->HasPointerMap()); |
| 3714 | 3715 |
| 3715 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 3716 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); |
| 3716 if (known_function.is_null()) { | 3717 if (known_function.is_null()) { |
| 3717 LPointerMap* pointers = instr->pointer_map(); | 3718 LPointerMap* pointers = instr->pointer_map(); |
| 3718 RecordPosition(pointers->position()); | |
| 3719 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3719 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 3720 ParameterCount count(instr->arity()); | 3720 ParameterCount count(instr->arity()); |
| 3721 __ InvokeFunction(rdi, count, CALL_FUNCTION, generator, CALL_AS_METHOD); | 3721 __ InvokeFunction(rdi, count, CALL_FUNCTION, generator, CALL_AS_METHOD); |
| 3722 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 3722 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 3723 } else { | 3723 } else { |
| 3724 CallKnownFunction(known_function, | 3724 CallKnownFunction(known_function, |
| 3725 instr->hydrogen()->formal_parameter_count(), | 3725 instr->hydrogen()->formal_parameter_count(), |
| 3726 instr->arity(), | 3726 instr->arity(), |
| 3727 instr, | 3727 instr, |
| 3728 CALL_AS_METHOD, | 3728 CALL_AS_METHOD, |
| (...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4258 RecordSafepointWithRegisters( | 4258 RecordSafepointWithRegisters( |
| 4259 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 4259 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
| 4260 } | 4260 } |
| 4261 __ bind(¬_applicable); | 4261 __ bind(¬_applicable); |
| 4262 } | 4262 } |
| 4263 | 4263 |
| 4264 | 4264 |
| 4265 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { | 4265 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { |
| 4266 Register object = ToRegister(instr->object()); | 4266 Register object = ToRegister(instr->object()); |
| 4267 Register temp = ToRegister(instr->temp()); | 4267 Register temp = ToRegister(instr->temp()); |
| 4268 __ TestJSArrayForAllocationMemento(object, temp); | 4268 Label no_memento_found; |
| 4269 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); |
| 4269 DeoptimizeIf(equal, instr->environment()); | 4270 DeoptimizeIf(equal, instr->environment()); |
| 4271 __ bind(&no_memento_found); |
| 4270 } | 4272 } |
| 4271 | 4273 |
| 4272 | 4274 |
| 4273 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 4275 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
| 4274 EmitPushTaggedOperand(instr->left()); | 4276 EmitPushTaggedOperand(instr->left()); |
| 4275 EmitPushTaggedOperand(instr->right()); | 4277 EmitPushTaggedOperand(instr->right()); |
| 4276 StringAddStub stub(instr->hydrogen()->flags()); | 4278 StringAddStub stub(instr->hydrogen()->flags()); |
| 4277 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4279 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 4278 } | 4280 } |
| 4279 | 4281 |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4412 LOperand* input = instr->value(); | 4414 LOperand* input = instr->value(); |
| 4413 LOperand* output = instr->result(); | 4415 LOperand* output = instr->result(); |
| 4414 LOperand* temp = instr->temp(); | 4416 LOperand* temp = instr->temp(); |
| 4415 | 4417 |
| 4416 __ LoadUint32(ToDoubleRegister(output), | 4418 __ LoadUint32(ToDoubleRegister(output), |
| 4417 ToRegister(input), | 4419 ToRegister(input), |
| 4418 ToDoubleRegister(temp)); | 4420 ToDoubleRegister(temp)); |
| 4419 } | 4421 } |
| 4420 | 4422 |
| 4421 | 4423 |
| 4424 void LCodeGen::DoUint32ToSmi(LUint32ToSmi* instr) { |
| 4425 LOperand* input = instr->value(); |
| 4426 ASSERT(input->IsRegister()); |
| 4427 LOperand* output = instr->result(); |
| 4428 if (!instr->hydrogen()->value()->HasRange() || |
| 4429 !instr->hydrogen()->value()->range()->IsInSmiRange() || |
| 4430 instr->hydrogen()->value()->range()->upper() == kMaxInt) { |
| 4431 // The Range class can't express upper bounds in the (kMaxInt, kMaxUint32] |
| 4432 // interval, so we treat kMaxInt as a sentinel for this entire interval. |
| 4433 __ testl(ToRegister(input), Immediate(0x80000000)); |
| 4434 DeoptimizeIf(not_zero, instr->environment()); |
| 4435 } |
| 4436 __ Integer32ToSmi(ToRegister(output), ToRegister(input)); |
| 4437 } |
| 4438 |
| 4439 |
| 4422 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { | 4440 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
| 4423 LOperand* input = instr->value(); | 4441 LOperand* input = instr->value(); |
| 4424 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4442 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
| 4425 Register reg = ToRegister(input); | 4443 Register reg = ToRegister(input); |
| 4426 | 4444 |
| 4427 __ Integer32ToSmi(reg, reg); | 4445 __ Integer32ToSmi(reg, reg); |
| 4428 } | 4446 } |
| 4429 | 4447 |
| 4430 | 4448 |
| 4431 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { | 4449 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4613 | 4631 |
| 4614 // Smi to XMM conversion | 4632 // Smi to XMM conversion |
| 4615 __ bind(&load_smi); | 4633 __ bind(&load_smi); |
| 4616 __ SmiToInteger32(kScratchRegister, input_reg); | 4634 __ SmiToInteger32(kScratchRegister, input_reg); |
| 4617 __ Cvtlsi2sd(result_reg, kScratchRegister); | 4635 __ Cvtlsi2sd(result_reg, kScratchRegister); |
| 4618 __ bind(&done); | 4636 __ bind(&done); |
| 4619 } | 4637 } |
| 4620 | 4638 |
| 4621 | 4639 |
| 4622 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) { | 4640 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) { |
| 4623 Label heap_number; | |
| 4624 Register input_reg = ToRegister(instr->value()); | 4641 Register input_reg = ToRegister(instr->value()); |
| 4625 | 4642 |
| 4643 if (instr->truncating()) { |
| 4644 Label no_heap_number, check_bools, check_false; |
| 4626 | 4645 |
| 4627 if (instr->truncating()) { | |
| 4628 // Heap number map check. | 4646 // Heap number map check. |
| 4629 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), | 4647 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 4630 Heap::kHeapNumberMapRootIndex); | 4648 Heap::kHeapNumberMapRootIndex); |
| 4631 __ j(equal, &heap_number, Label::kNear); | 4649 __ j(not_equal, &no_heap_number, Label::kNear); |
| 4632 // Check for undefined. Undefined is converted to zero for truncating | 4650 __ TruncateHeapNumberToI(input_reg, input_reg); |
| 4633 // conversions. | 4651 __ jmp(done); |
| 4652 |
| 4653 __ bind(&no_heap_number); |
| 4654 // Check for Oddballs. Undefined/False is converted to zero and True to one |
| 4655 // for truncating conversions. |
| 4634 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); | 4656 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); |
| 4657 __ j(not_equal, &check_bools, Label::kNear); |
| 4658 __ Set(input_reg, 0); |
| 4659 __ jmp(done); |
| 4660 |
| 4661 __ bind(&check_bools); |
| 4662 __ CompareRoot(input_reg, Heap::kTrueValueRootIndex); |
| 4663 __ j(not_equal, &check_false, Label::kNear); |
| 4664 __ Set(input_reg, 1); |
| 4665 __ jmp(done); |
| 4666 |
| 4667 __ bind(&check_false); |
| 4668 __ CompareRoot(input_reg, Heap::kFalseValueRootIndex); |
| 4669 __ RecordComment("Deferred TaggedToI: cannot truncate"); |
| 4635 DeoptimizeIf(not_equal, instr->environment()); | 4670 DeoptimizeIf(not_equal, instr->environment()); |
| 4636 __ Set(input_reg, 0); | 4671 __ Set(input_reg, 0); |
| 4637 __ jmp(done); | 4672 __ jmp(done); |
| 4638 | |
| 4639 __ bind(&heap_number); | |
| 4640 __ TruncateHeapNumberToI(input_reg, input_reg); | |
| 4641 } else { | 4673 } else { |
| 4642 Label bailout; | 4674 Label bailout; |
| 4643 XMMRegister xmm_temp = ToDoubleRegister(instr->temp()); | 4675 XMMRegister xmm_temp = ToDoubleRegister(instr->temp()); |
| 4644 __ TaggedToI(input_reg, input_reg, xmm_temp, | 4676 __ TaggedToI(input_reg, input_reg, xmm_temp, |
| 4645 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); | 4677 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); |
| 4646 | 4678 |
| 4647 __ jmp(done); | 4679 __ jmp(done); |
| 4648 __ bind(&bailout); | 4680 __ bind(&bailout); |
| 4649 DeoptimizeIf(no_condition, instr->environment()); | 4681 DeoptimizeIf(no_condition, instr->environment()); |
| 4650 } | 4682 } |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4807 __ andb(kScratchRegister, Immediate(mask)); | 4839 __ andb(kScratchRegister, Immediate(mask)); |
| 4808 __ cmpb(kScratchRegister, Immediate(tag)); | 4840 __ cmpb(kScratchRegister, Immediate(tag)); |
| 4809 DeoptimizeIf(not_equal, instr->environment()); | 4841 DeoptimizeIf(not_equal, instr->environment()); |
| 4810 } | 4842 } |
| 4811 } | 4843 } |
| 4812 } | 4844 } |
| 4813 | 4845 |
| 4814 | 4846 |
| 4815 void LCodeGen::DoCheckValue(LCheckValue* instr) { | 4847 void LCodeGen::DoCheckValue(LCheckValue* instr) { |
| 4816 Register reg = ToRegister(instr->value()); | 4848 Register reg = ToRegister(instr->value()); |
| 4817 Handle<HeapObject> object = instr->hydrogen()->object().handle(); | 4849 __ Cmp(reg, instr->hydrogen()->object().handle()); |
| 4818 __ CmpHeapObject(reg, object); | |
| 4819 DeoptimizeIf(not_equal, instr->environment()); | 4850 DeoptimizeIf(not_equal, instr->environment()); |
| 4820 } | 4851 } |
| 4821 | 4852 |
| 4822 | 4853 |
| 4823 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { | 4854 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { |
| 4824 { | 4855 { |
| 4825 PushSafepointRegistersScope scope(this); | 4856 PushSafepointRegistersScope scope(this); |
| 4826 __ push(object); | 4857 __ push(object); |
| 4827 CallRuntimeFromDeferred(Runtime::kMigrateInstance, 1, instr); | 4858 CallRuntimeFromDeferred(Runtime::kMigrateInstance, 1, instr); |
| 4828 __ testq(rax, Immediate(kSmiTagMask)); | 4859 __ testq(rax, Immediate(kSmiTagMask)); |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5035 | 5066 |
| 5036 | 5067 |
| 5037 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { | 5068 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { |
| 5038 Label materialized; | 5069 Label materialized; |
| 5039 // Registers will be used as follows: | 5070 // Registers will be used as follows: |
| 5040 // rcx = literals array. | 5071 // rcx = literals array. |
| 5041 // rbx = regexp literal. | 5072 // rbx = regexp literal. |
| 5042 // rax = regexp literal clone. | 5073 // rax = regexp literal clone. |
| 5043 int literal_offset = | 5074 int literal_offset = |
| 5044 FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index()); | 5075 FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index()); |
| 5045 __ LoadHeapObject(rcx, instr->hydrogen()->literals()); | 5076 __ Move(rcx, instr->hydrogen()->literals()); |
| 5046 __ movq(rbx, FieldOperand(rcx, literal_offset)); | 5077 __ movq(rbx, FieldOperand(rcx, literal_offset)); |
| 5047 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); | 5078 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); |
| 5048 __ j(not_equal, &materialized, Label::kNear); | 5079 __ j(not_equal, &materialized, Label::kNear); |
| 5049 | 5080 |
| 5050 // Create regexp literal using runtime function | 5081 // Create regexp literal using runtime function |
| 5051 // Result will be in rax. | 5082 // Result will be in rax. |
| 5052 __ push(rcx); | 5083 __ push(rcx); |
| 5053 __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); | 5084 __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); |
| 5054 __ Push(instr->hydrogen()->pattern()); | 5085 __ Push(instr->hydrogen()->pattern()); |
| 5055 __ Push(instr->hydrogen()->flags()); | 5086 __ Push(instr->hydrogen()->flags()); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5106 void LCodeGen::DoTypeof(LTypeof* instr) { | 5137 void LCodeGen::DoTypeof(LTypeof* instr) { |
| 5107 LOperand* input = instr->value(); | 5138 LOperand* input = instr->value(); |
| 5108 EmitPushTaggedOperand(input); | 5139 EmitPushTaggedOperand(input); |
| 5109 CallRuntime(Runtime::kTypeof, 1, instr); | 5140 CallRuntime(Runtime::kTypeof, 1, instr); |
| 5110 } | 5141 } |
| 5111 | 5142 |
| 5112 | 5143 |
| 5113 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { | 5144 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { |
| 5114 ASSERT(!operand->IsDoubleRegister()); | 5145 ASSERT(!operand->IsDoubleRegister()); |
| 5115 if (operand->IsConstantOperand()) { | 5146 if (operand->IsConstantOperand()) { |
| 5116 Handle<Object> object = ToHandle(LConstantOperand::cast(operand)); | 5147 __ Push(ToHandle(LConstantOperand::cast(operand))); |
| 5117 AllowDeferredHandleDereference smi_check; | |
| 5118 if (object->IsSmi()) { | |
| 5119 __ Push(Handle<Smi>::cast(object)); | |
| 5120 } else { | |
| 5121 __ PushHeapObject(Handle<HeapObject>::cast(object)); | |
| 5122 } | |
| 5123 } else if (operand->IsRegister()) { | 5148 } else if (operand->IsRegister()) { |
| 5124 __ push(ToRegister(operand)); | 5149 __ push(ToRegister(operand)); |
| 5125 } else { | 5150 } else { |
| 5126 __ push(ToOperand(operand)); | 5151 __ push(ToOperand(operand)); |
| 5127 } | 5152 } |
| 5128 } | 5153 } |
| 5129 | 5154 |
| 5130 | 5155 |
| 5131 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 5156 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
| 5132 Register input = ToRegister(instr->value()); | 5157 Register input = ToRegister(instr->value()); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5226 | 5251 |
| 5227 void LCodeGen::EmitIsConstructCall(Register temp) { | 5252 void LCodeGen::EmitIsConstructCall(Register temp) { |
| 5228 // Get the frame pointer for the calling frame. | 5253 // Get the frame pointer for the calling frame. |
| 5229 __ movq(temp, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 5254 __ movq(temp, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
| 5230 | 5255 |
| 5231 // Skip the arguments adaptor frame if it exists. | 5256 // Skip the arguments adaptor frame if it exists. |
| 5232 Label check_frame_marker; | 5257 Label check_frame_marker; |
| 5233 __ Cmp(Operand(temp, StandardFrameConstants::kContextOffset), | 5258 __ Cmp(Operand(temp, StandardFrameConstants::kContextOffset), |
| 5234 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | 5259 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
| 5235 __ j(not_equal, &check_frame_marker, Label::kNear); | 5260 __ j(not_equal, &check_frame_marker, Label::kNear); |
| 5236 __ movq(temp, Operand(rax, StandardFrameConstants::kCallerFPOffset)); | 5261 __ movq(temp, Operand(temp, StandardFrameConstants::kCallerFPOffset)); |
| 5237 | 5262 |
| 5238 // Check the marker in the calling frame. | 5263 // Check the marker in the calling frame. |
| 5239 __ bind(&check_frame_marker); | 5264 __ bind(&check_frame_marker); |
| 5240 __ Cmp(Operand(temp, StandardFrameConstants::kMarkerOffset), | 5265 __ Cmp(Operand(temp, StandardFrameConstants::kMarkerOffset), |
| 5241 Smi::FromInt(StackFrame::CONSTRUCT)); | 5266 Smi::FromInt(StackFrame::CONSTRUCT)); |
| 5242 } | 5267 } |
| 5243 | 5268 |
| 5244 | 5269 |
| 5245 void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) { | 5270 void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) { |
| 5246 if (info()->IsStub()) return; | 5271 if (info()->IsStub()) return; |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5446 FixedArray::kHeaderSize - kPointerSize)); | 5471 FixedArray::kHeaderSize - kPointerSize)); |
| 5447 __ bind(&done); | 5472 __ bind(&done); |
| 5448 } | 5473 } |
| 5449 | 5474 |
| 5450 | 5475 |
| 5451 #undef __ | 5476 #undef __ |
| 5452 | 5477 |
| 5453 } } // namespace v8::internal | 5478 } } // namespace v8::internal |
| 5454 | 5479 |
| 5455 #endif // V8_TARGET_ARCH_X64 | 5480 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |