| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 | 125 |
| 126 ProfileEntryHookStub::MaybeCallEntryHook(masm_); | 126 ProfileEntryHookStub::MaybeCallEntryHook(masm_); |
| 127 | 127 |
| 128 #ifdef DEBUG | 128 #ifdef DEBUG |
| 129 if (strlen(FLAG_stop_at) > 0 && | 129 if (strlen(FLAG_stop_at) > 0 && |
| 130 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { | 130 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { |
| 131 __ int3(); | 131 __ int3(); |
| 132 } | 132 } |
| 133 #endif | 133 #endif |
| 134 | 134 |
| 135 // Strict mode functions and builtins need to replace the receiver | 135 // Classic mode functions and builtins need to replace the receiver with the |
| 136 // with undefined when called as functions (without an explicit | 136 // global proxy when called as functions (without an explicit receiver |
| 137 // receiver object). rcx is zero for method calls and non-zero for | 137 // object). |
| 138 // function calls. | 138 if (info->is_classic_mode() && !info->is_native()) { |
| 139 if (!info->is_classic_mode() || info->is_native()) { | |
| 140 Label ok; | 139 Label ok; |
| 141 __ testq(rcx, rcx); | 140 __ testq(rcx, rcx); |
| 142 __ j(zero, &ok, Label::kNear); | 141 __ j(zero, &ok, Label::kNear); |
| 142 |
| 143 // +1 for return address. |
| 143 StackArgumentsAccessor args(rsp, info->scope()->num_parameters()); | 144 StackArgumentsAccessor args(rsp, info->scope()->num_parameters()); |
| 144 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); | 145 __ movq(rcx, args.GetReceiverOperand()); |
| 145 __ movq(args.GetReceiverOperand(), kScratchRegister); | 146 |
| 147 __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex); |
| 148 __ j(not_equal, &ok, Label::kNear); |
| 149 |
| 150 __ movq(rcx, GlobalObjectOperand()); |
| 151 __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); |
| 152 |
| 153 __ movq(args.GetReceiverOperand(), rcx); |
| 154 |
| 146 __ bind(&ok); | 155 __ bind(&ok); |
| 147 } | 156 } |
| 148 | 157 |
| 149 // Open a frame scope to indicate that there is a frame on the stack. The | 158 // Open a frame scope to indicate that there is a frame on the stack. The |
| 150 // MANUAL indicates that the scope shouldn't actually generate code to set up | 159 // MANUAL indicates that the scope shouldn't actually generate code to set up |
| 151 // the frame (that is done below). | 160 // the frame (that is done below). |
| 152 FrameScope frame_scope(masm_, StackFrame::MANUAL); | 161 FrameScope frame_scope(masm_, StackFrame::MANUAL); |
| 153 | 162 |
| 154 info->set_prologue_offset(masm_->pc_offset()); | 163 info->set_prologue_offset(masm_->pc_offset()); |
| 155 __ Prologue(BUILD_FUNCTION_FRAME); | 164 __ Prologue(BUILD_FUNCTION_FRAME); |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 } | 304 } |
| 296 } | 305 } |
| 297 | 306 |
| 298 | 307 |
| 299 void FullCodeGenerator::ClearAccumulator() { | 308 void FullCodeGenerator::ClearAccumulator() { |
| 300 __ Set(rax, 0); | 309 __ Set(rax, 0); |
| 301 } | 310 } |
| 302 | 311 |
| 303 | 312 |
| 304 void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) { | 313 void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) { |
| 305 __ movq(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT); | 314 __ Move(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT); |
| 306 __ SmiAddConstant(FieldOperand(rbx, Cell::kValueOffset), | 315 __ SmiAddConstant(FieldOperand(rbx, Cell::kValueOffset), |
| 307 Smi::FromInt(-delta)); | 316 Smi::FromInt(-delta)); |
| 308 } | 317 } |
| 309 | 318 |
| 310 | 319 |
| 311 void FullCodeGenerator::EmitProfilingCounterReset() { | 320 void FullCodeGenerator::EmitProfilingCounterReset() { |
| 312 int reset_value = FLAG_interrupt_budget; | 321 int reset_value = FLAG_interrupt_budget; |
| 313 __ movq(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT); | 322 __ Move(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT); |
| 314 __ Move(kScratchRegister, Smi::FromInt(reset_value)); | 323 __ Move(kScratchRegister, Smi::FromInt(reset_value)); |
| 315 __ movq(FieldOperand(rbx, Cell::kValueOffset), kScratchRegister); | 324 __ movq(FieldOperand(rbx, Cell::kValueOffset), kScratchRegister); |
| 316 } | 325 } |
| 317 | 326 |
| 318 | 327 |
| 319 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt, | 328 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt, |
| 320 Label* back_edge_target) { | 329 Label* back_edge_target) { |
| 321 Comment cmnt(masm_, "[ Back edge bookkeeping"); | 330 Comment cmnt(masm_, "[ Back edge bookkeeping"); |
| 322 Label ok; | 331 Label ok; |
| 323 | 332 |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 623 if (false_label_ != fall_through_) __ jmp(false_label_); | 632 if (false_label_ != fall_through_) __ jmp(false_label_); |
| 624 } | 633 } |
| 625 } | 634 } |
| 626 | 635 |
| 627 | 636 |
| 628 void FullCodeGenerator::DoTest(Expression* condition, | 637 void FullCodeGenerator::DoTest(Expression* condition, |
| 629 Label* if_true, | 638 Label* if_true, |
| 630 Label* if_false, | 639 Label* if_false, |
| 631 Label* fall_through) { | 640 Label* fall_through) { |
| 632 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); | 641 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); |
| 633 CallIC(ic, RelocInfo::CODE_TARGET, condition->test_id()); | 642 CallIC(ic, NOT_CONTEXTUAL, condition->test_id()); |
| 634 __ testq(result_register(), result_register()); | 643 __ testq(result_register(), result_register()); |
| 635 // The stub returns nonzero for true. | 644 // The stub returns nonzero for true. |
| 636 Split(not_zero, if_true, if_false, fall_through); | 645 Split(not_zero, if_true, if_false, fall_through); |
| 637 } | 646 } |
| 638 | 647 |
| 639 | 648 |
| 640 void FullCodeGenerator::Split(Condition cc, | 649 void FullCodeGenerator::Split(Condition cc, |
| 641 Label* if_true, | 650 Label* if_true, |
| 642 Label* if_false, | 651 Label* if_false, |
| 643 Label* fall_through) { | 652 Label* fall_through) { |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 976 __ cmpq(rdx, rax); | 985 __ cmpq(rdx, rax); |
| 977 __ j(not_equal, &next_test); | 986 __ j(not_equal, &next_test); |
| 978 __ Drop(1); // Switch value is no longer needed. | 987 __ Drop(1); // Switch value is no longer needed. |
| 979 __ jmp(clause->body_target()); | 988 __ jmp(clause->body_target()); |
| 980 __ bind(&slow_case); | 989 __ bind(&slow_case); |
| 981 } | 990 } |
| 982 | 991 |
| 983 // Record position before stub call for type feedback. | 992 // Record position before stub call for type feedback. |
| 984 SetSourcePosition(clause->position()); | 993 SetSourcePosition(clause->position()); |
| 985 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); | 994 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); |
| 986 CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId()); | 995 CallIC(ic, NOT_CONTEXTUAL, clause->CompareId()); |
| 987 patch_site.EmitPatchInfo(); | 996 patch_site.EmitPatchInfo(); |
| 988 | 997 |
| 989 Label skip; | 998 Label skip; |
| 990 __ jmp(&skip, Label::kNear); | 999 __ jmp(&skip, Label::kNear); |
| 991 PrepareForBailout(clause, TOS_REG); | 1000 PrepareForBailout(clause, TOS_REG); |
| 992 __ CompareRoot(rax, Heap::kTrueValueRootIndex); | 1001 __ CompareRoot(rax, Heap::kTrueValueRootIndex); |
| 993 __ j(not_equal, &next_test); | 1002 __ j(not_equal, &next_test); |
| 994 __ Drop(1); | 1003 __ Drop(1); |
| 995 __ jmp(clause->body_target()); | 1004 __ jmp(clause->body_target()); |
| 996 __ bind(&skip); | 1005 __ bind(&skip); |
| (...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1346 // Load next context in chain. | 1355 // Load next context in chain. |
| 1347 __ movq(temp, ContextOperand(temp, Context::PREVIOUS_INDEX)); | 1356 __ movq(temp, ContextOperand(temp, Context::PREVIOUS_INDEX)); |
| 1348 __ jmp(&next); | 1357 __ jmp(&next); |
| 1349 __ bind(&fast); | 1358 __ bind(&fast); |
| 1350 } | 1359 } |
| 1351 | 1360 |
| 1352 // All extension objects were empty and it is safe to use a global | 1361 // All extension objects were empty and it is safe to use a global |
| 1353 // load IC call. | 1362 // load IC call. |
| 1354 __ movq(rax, GlobalObjectOperand()); | 1363 __ movq(rax, GlobalObjectOperand()); |
| 1355 __ Move(rcx, var->name()); | 1364 __ Move(rcx, var->name()); |
| 1356 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1365 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) |
| 1357 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) | 1366 ? NOT_CONTEXTUAL |
| 1358 ? RelocInfo::CODE_TARGET | 1367 : CONTEXTUAL; |
| 1359 : RelocInfo::CODE_TARGET_CONTEXT; | 1368 CallLoadIC(mode); |
| 1360 CallIC(ic, mode); | |
| 1361 } | 1369 } |
| 1362 | 1370 |
| 1363 | 1371 |
| 1364 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1372 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
| 1365 Label* slow) { | 1373 Label* slow) { |
| 1366 ASSERT(var->IsContextSlot()); | 1374 ASSERT(var->IsContextSlot()); |
| 1367 Register context = rsi; | 1375 Register context = rsi; |
| 1368 Register temp = rbx; | 1376 Register temp = rbx; |
| 1369 | 1377 |
| 1370 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { | 1378 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1430 | 1438 |
| 1431 // Three cases: global variables, lookup variables, and all other types of | 1439 // Three cases: global variables, lookup variables, and all other types of |
| 1432 // variables. | 1440 // variables. |
| 1433 switch (var->location()) { | 1441 switch (var->location()) { |
| 1434 case Variable::UNALLOCATED: { | 1442 case Variable::UNALLOCATED: { |
| 1435 Comment cmnt(masm_, "Global variable"); | 1443 Comment cmnt(masm_, "Global variable"); |
| 1436 // Use inline caching. Variable name is passed in rcx and the global | 1444 // Use inline caching. Variable name is passed in rcx and the global |
| 1437 // object on the stack. | 1445 // object on the stack. |
| 1438 __ Move(rcx, var->name()); | 1446 __ Move(rcx, var->name()); |
| 1439 __ movq(rax, GlobalObjectOperand()); | 1447 __ movq(rax, GlobalObjectOperand()); |
| 1440 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1448 CallLoadIC(CONTEXTUAL); |
| 1441 CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); | |
| 1442 context()->Plug(rax); | 1449 context()->Plug(rax); |
| 1443 break; | 1450 break; |
| 1444 } | 1451 } |
| 1445 | 1452 |
| 1446 case Variable::PARAMETER: | 1453 case Variable::PARAMETER: |
| 1447 case Variable::LOCAL: | 1454 case Variable::LOCAL: |
| 1448 case Variable::CONTEXT: { | 1455 case Variable::CONTEXT: { |
| 1449 Comment cmnt(masm_, var->IsContextSlot() ? "Context slot" : "Stack slot"); | 1456 Comment cmnt(masm_, var->IsContextSlot() ? "Context slot" : "Stack slot"); |
| 1450 if (var->binding_needs_init()) { | 1457 if (var->binding_needs_init()) { |
| 1451 // var->scope() may be NULL when the proxy is located in eval code and | 1458 // var->scope() may be NULL when the proxy is located in eval code and |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1645 UNREACHABLE(); | 1652 UNREACHABLE(); |
| 1646 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1653 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1647 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); | 1654 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); |
| 1648 // Fall through. | 1655 // Fall through. |
| 1649 case ObjectLiteral::Property::COMPUTED: | 1656 case ObjectLiteral::Property::COMPUTED: |
| 1650 if (key->value()->IsInternalizedString()) { | 1657 if (key->value()->IsInternalizedString()) { |
| 1651 if (property->emit_store()) { | 1658 if (property->emit_store()) { |
| 1652 VisitForAccumulatorValue(value); | 1659 VisitForAccumulatorValue(value); |
| 1653 __ Move(rcx, key->value()); | 1660 __ Move(rcx, key->value()); |
| 1654 __ movq(rdx, Operand(rsp, 0)); | 1661 __ movq(rdx, Operand(rsp, 0)); |
| 1655 Handle<Code> ic = is_classic_mode() | 1662 CallStoreIC(NOT_CONTEXTUAL, key->LiteralFeedbackId()); |
| 1656 ? isolate()->builtins()->StoreIC_Initialize() | |
| 1657 : isolate()->builtins()->StoreIC_Initialize_Strict(); | |
| 1658 CallIC(ic, RelocInfo::CODE_TARGET, key->LiteralFeedbackId()); | |
| 1659 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1663 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
| 1660 } else { | 1664 } else { |
| 1661 VisitForEffect(value); | 1665 VisitForEffect(value); |
| 1662 } | 1666 } |
| 1663 break; | 1667 break; |
| 1664 } | 1668 } |
| 1665 __ push(Operand(rsp, 0)); // Duplicate receiver. | 1669 __ push(Operand(rsp, 0)); // Duplicate receiver. |
| 1666 VisitForStackValue(key); | 1670 VisitForStackValue(key); |
| 1667 VisitForStackValue(value); | 1671 VisitForStackValue(value); |
| 1668 if (property->emit_store()) { | 1672 if (property->emit_store()) { |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1729 int length = subexprs->length(); | 1733 int length = subexprs->length(); |
| 1730 Handle<FixedArray> constant_elements = expr->constant_elements(); | 1734 Handle<FixedArray> constant_elements = expr->constant_elements(); |
| 1731 ASSERT_EQ(2, constant_elements->length()); | 1735 ASSERT_EQ(2, constant_elements->length()); |
| 1732 ElementsKind constant_elements_kind = | 1736 ElementsKind constant_elements_kind = |
| 1733 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); | 1737 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); |
| 1734 bool has_constant_fast_elements = | 1738 bool has_constant_fast_elements = |
| 1735 IsFastObjectElementsKind(constant_elements_kind); | 1739 IsFastObjectElementsKind(constant_elements_kind); |
| 1736 Handle<FixedArrayBase> constant_elements_values( | 1740 Handle<FixedArrayBase> constant_elements_values( |
| 1737 FixedArrayBase::cast(constant_elements->get(1))); | 1741 FixedArrayBase::cast(constant_elements->get(1))); |
| 1738 | 1742 |
| 1739 AllocationSiteMode allocation_site_mode = FLAG_track_allocation_sites | 1743 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE; |
| 1740 ? TRACK_ALLOCATION_SITE : DONT_TRACK_ALLOCATION_SITE; | |
| 1741 if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) { | 1744 if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) { |
| 1742 // If the only customer of allocation sites is transitioning, then | 1745 // If the only customer of allocation sites is transitioning, then |
| 1743 // we can turn it off if we don't have anywhere else to transition to. | 1746 // we can turn it off if we don't have anywhere else to transition to. |
| 1744 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; | 1747 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; |
| 1745 } | 1748 } |
| 1746 | 1749 |
| 1747 Heap* heap = isolate()->heap(); | 1750 Heap* heap = isolate()->heap(); |
| 1748 if (has_constant_fast_elements && | 1751 if (has_constant_fast_elements && |
| 1749 constant_elements_values->map() == heap->fixed_cow_array_map()) { | 1752 constant_elements_values->map() == heap->fixed_cow_array_map()) { |
| 1750 // If the elements are already FAST_*_ELEMENTS, the boilerplate cannot | 1753 // If the elements are already FAST_*_ELEMENTS, the boilerplate cannot |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2070 __ bind(&l_call); | 2073 __ bind(&l_call); |
| 2071 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); | 2074 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); |
| 2072 CallIC(ic); | 2075 CallIC(ic); |
| 2073 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2076 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 2074 __ Drop(1); // The key is still on the stack; drop it. | 2077 __ Drop(1); // The key is still on the stack; drop it. |
| 2075 | 2078 |
| 2076 // if (!result.done) goto l_try; | 2079 // if (!result.done) goto l_try; |
| 2077 __ bind(&l_loop); | 2080 __ bind(&l_loop); |
| 2078 __ push(rax); // save result | 2081 __ push(rax); // save result |
| 2079 __ LoadRoot(rcx, Heap::kdone_stringRootIndex); // "done" | 2082 __ LoadRoot(rcx, Heap::kdone_stringRootIndex); // "done" |
| 2080 Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize(); | 2083 CallLoadIC(NOT_CONTEXTUAL); // result.done in rax |
| 2081 CallIC(done_ic); // result.done in rax | |
| 2082 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); | 2084 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); |
| 2083 CallIC(bool_ic); | 2085 CallIC(bool_ic); |
| 2084 __ testq(result_register(), result_register()); | 2086 __ testq(result_register(), result_register()); |
| 2085 __ j(zero, &l_try); | 2087 __ j(zero, &l_try); |
| 2086 | 2088 |
| 2087 // result.value | 2089 // result.value |
| 2088 __ pop(rax); // result | 2090 __ pop(rax); // result |
| 2089 __ LoadRoot(rcx, Heap::kvalue_stringRootIndex); // "value" | 2091 __ LoadRoot(rcx, Heap::kvalue_stringRootIndex); // "value" |
| 2090 Handle<Code> value_ic = isolate()->builtins()->LoadIC_Initialize(); | 2092 CallLoadIC(NOT_CONTEXTUAL); // result.value in rax |
| 2091 CallIC(value_ic); // result.value in rax | |
| 2092 context()->DropAndPlug(2, rax); // drop iter and g | 2093 context()->DropAndPlug(2, rax); // drop iter and g |
| 2093 break; | 2094 break; |
| 2094 } | 2095 } |
| 2095 } | 2096 } |
| 2096 } | 2097 } |
| 2097 | 2098 |
| 2098 | 2099 |
| 2099 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, | 2100 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, |
| 2100 Expression *value, | 2101 Expression *value, |
| 2101 JSGeneratorObject::ResumeMode resume_mode) { | 2102 JSGeneratorObject::ResumeMode resume_mode) { |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2227 // root set. | 2228 // root set. |
| 2228 __ RecordWriteField(rax, JSGeneratorObject::kResultValuePropertyOffset, | 2229 __ RecordWriteField(rax, JSGeneratorObject::kResultValuePropertyOffset, |
| 2229 rcx, rdx, kDontSaveFPRegs); | 2230 rcx, rdx, kDontSaveFPRegs); |
| 2230 } | 2231 } |
| 2231 | 2232 |
| 2232 | 2233 |
| 2233 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 2234 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
| 2234 SetSourcePosition(prop->position()); | 2235 SetSourcePosition(prop->position()); |
| 2235 Literal* key = prop->key()->AsLiteral(); | 2236 Literal* key = prop->key()->AsLiteral(); |
| 2236 __ Move(rcx, key->value()); | 2237 __ Move(rcx, key->value()); |
| 2237 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2238 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); |
| 2238 CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); | |
| 2239 } | 2239 } |
| 2240 | 2240 |
| 2241 | 2241 |
| 2242 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 2242 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
| 2243 SetSourcePosition(prop->position()); | 2243 SetSourcePosition(prop->position()); |
| 2244 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2244 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 2245 CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); | 2245 CallIC(ic, NOT_CONTEXTUAL, prop->PropertyFeedbackId()); |
| 2246 } | 2246 } |
| 2247 | 2247 |
| 2248 | 2248 |
| 2249 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 2249 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
| 2250 Token::Value op, | 2250 Token::Value op, |
| 2251 OverwriteMode mode, | 2251 OverwriteMode mode, |
| 2252 Expression* left, | 2252 Expression* left, |
| 2253 Expression* right) { | 2253 Expression* right) { |
| 2254 // Do combined smi check of the operands. Left operand is on the | 2254 // Do combined smi check of the operands. Left operand is on the |
| 2255 // stack (popped into rdx). Right operand is in rax but moved into | 2255 // stack (popped into rdx). Right operand is in rax but moved into |
| 2256 // rcx to make the shifts easier. | 2256 // rcx to make the shifts easier. |
| 2257 Label done, stub_call, smi_case; | 2257 Label done, stub_call, smi_case; |
| 2258 __ pop(rdx); | 2258 __ pop(rdx); |
| 2259 __ movq(rcx, rax); | 2259 __ movq(rcx, rax); |
| 2260 __ or_(rax, rdx); | 2260 __ or_(rax, rdx); |
| 2261 JumpPatchSite patch_site(masm_); | 2261 JumpPatchSite patch_site(masm_); |
| 2262 patch_site.EmitJumpIfSmi(rax, &smi_case, Label::kNear); | 2262 patch_site.EmitJumpIfSmi(rax, &smi_case, Label::kNear); |
| 2263 | 2263 |
| 2264 __ bind(&stub_call); | 2264 __ bind(&stub_call); |
| 2265 __ movq(rax, rcx); | 2265 __ movq(rax, rcx); |
| 2266 BinaryOpICStub stub(op, mode); | 2266 BinaryOpICStub stub(op, mode); |
| 2267 CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, | 2267 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, |
| 2268 expr->BinaryOperationFeedbackId()); | 2268 expr->BinaryOperationFeedbackId()); |
| 2269 patch_site.EmitPatchInfo(); | 2269 patch_site.EmitPatchInfo(); |
| 2270 __ jmp(&done, Label::kNear); | 2270 __ jmp(&done, Label::kNear); |
| 2271 | 2271 |
| 2272 __ bind(&smi_case); | 2272 __ bind(&smi_case); |
| 2273 switch (op) { | 2273 switch (op) { |
| 2274 case Token::SAR: | 2274 case Token::SAR: |
| 2275 __ SmiShiftArithmeticRight(rax, rdx, rcx); | 2275 __ SmiShiftArithmeticRight(rax, rdx, rcx); |
| 2276 break; | 2276 break; |
| 2277 case Token::SHL: | 2277 case Token::SHL: |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2307 context()->Plug(rax); | 2307 context()->Plug(rax); |
| 2308 } | 2308 } |
| 2309 | 2309 |
| 2310 | 2310 |
| 2311 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, | 2311 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, |
| 2312 Token::Value op, | 2312 Token::Value op, |
| 2313 OverwriteMode mode) { | 2313 OverwriteMode mode) { |
| 2314 __ pop(rdx); | 2314 __ pop(rdx); |
| 2315 BinaryOpICStub stub(op, mode); | 2315 BinaryOpICStub stub(op, mode); |
| 2316 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 2316 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
| 2317 CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, | 2317 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, |
| 2318 expr->BinaryOperationFeedbackId()); | 2318 expr->BinaryOperationFeedbackId()); |
| 2319 patch_site.EmitPatchInfo(); | 2319 patch_site.EmitPatchInfo(); |
| 2320 context()->Plug(rax); | 2320 context()->Plug(rax); |
| 2321 } | 2321 } |
| 2322 | 2322 |
| 2323 | 2323 |
| 2324 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 2324 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
| 2325 // Invalid left-hand sides are rewritten by the parser to have a 'throw | 2325 // Invalid left-hand sides are rewritten by the parser to have a 'throw |
| 2326 // ReferenceError' on the left-hand side. | 2326 // ReferenceError' on the left-hand side. |
| 2327 if (!expr->IsValidLeftHandSide()) { | 2327 if (!expr->IsValidLeftHandSide()) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2346 EffectContext context(this); | 2346 EffectContext context(this); |
| 2347 EmitVariableAssignment(var, Token::ASSIGN); | 2347 EmitVariableAssignment(var, Token::ASSIGN); |
| 2348 break; | 2348 break; |
| 2349 } | 2349 } |
| 2350 case NAMED_PROPERTY: { | 2350 case NAMED_PROPERTY: { |
| 2351 __ push(rax); // Preserve value. | 2351 __ push(rax); // Preserve value. |
| 2352 VisitForAccumulatorValue(prop->obj()); | 2352 VisitForAccumulatorValue(prop->obj()); |
| 2353 __ movq(rdx, rax); | 2353 __ movq(rdx, rax); |
| 2354 __ pop(rax); // Restore value. | 2354 __ pop(rax); // Restore value. |
| 2355 __ Move(rcx, prop->key()->AsLiteral()->value()); | 2355 __ Move(rcx, prop->key()->AsLiteral()->value()); |
| 2356 Handle<Code> ic = is_classic_mode() | 2356 CallStoreIC(NOT_CONTEXTUAL); |
| 2357 ? isolate()->builtins()->StoreIC_Initialize() | |
| 2358 : isolate()->builtins()->StoreIC_Initialize_Strict(); | |
| 2359 CallIC(ic); | |
| 2360 break; | 2357 break; |
| 2361 } | 2358 } |
| 2362 case KEYED_PROPERTY: { | 2359 case KEYED_PROPERTY: { |
| 2363 __ push(rax); // Preserve value. | 2360 __ push(rax); // Preserve value. |
| 2364 VisitForStackValue(prop->obj()); | 2361 VisitForStackValue(prop->obj()); |
| 2365 VisitForAccumulatorValue(prop->key()); | 2362 VisitForAccumulatorValue(prop->key()); |
| 2366 __ movq(rcx, rax); | 2363 __ movq(rcx, rax); |
| 2367 __ pop(rdx); | 2364 __ pop(rdx); |
| 2368 __ pop(rax); // Restore value. | 2365 __ pop(rax); // Restore value. |
| 2369 Handle<Code> ic = is_classic_mode() | 2366 Handle<Code> ic = is_classic_mode() |
| 2370 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2367 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2371 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2368 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2372 CallIC(ic); | 2369 CallIC(ic); |
| 2373 break; | 2370 break; |
| 2374 } | 2371 } |
| 2375 } | 2372 } |
| 2376 context()->Plug(rax); | 2373 context()->Plug(rax); |
| 2377 } | 2374 } |
| 2378 | 2375 |
| 2379 | 2376 |
| 2380 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 2377 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
| 2381 Token::Value op) { | 2378 Token::Value op) { |
| 2382 if (var->IsUnallocated()) { | 2379 if (var->IsUnallocated()) { |
| 2383 // Global var, const, or let. | 2380 // Global var, const, or let. |
| 2384 __ Move(rcx, var->name()); | 2381 __ Move(rcx, var->name()); |
| 2385 __ movq(rdx, GlobalObjectOperand()); | 2382 __ movq(rdx, GlobalObjectOperand()); |
| 2386 Handle<Code> ic = is_classic_mode() | 2383 CallStoreIC(CONTEXTUAL); |
| 2387 ? isolate()->builtins()->StoreIC_Initialize() | |
| 2388 : isolate()->builtins()->StoreIC_Initialize_Strict(); | |
| 2389 CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); | |
| 2390 } else if (op == Token::INIT_CONST) { | 2384 } else if (op == Token::INIT_CONST) { |
| 2391 // Const initializers need a write barrier. | 2385 // Const initializers need a write barrier. |
| 2392 ASSERT(!var->IsParameter()); // No const parameters. | 2386 ASSERT(!var->IsParameter()); // No const parameters. |
| 2393 if (var->IsStackLocal()) { | 2387 if (var->IsStackLocal()) { |
| 2394 Label skip; | 2388 Label skip; |
| 2395 __ movq(rdx, StackOperand(var)); | 2389 __ movq(rdx, StackOperand(var)); |
| 2396 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); | 2390 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); |
| 2397 __ j(not_equal, &skip); | 2391 __ j(not_equal, &skip); |
| 2398 __ movq(StackOperand(var), rax); | 2392 __ movq(StackOperand(var), rax); |
| 2399 __ bind(&skip); | 2393 __ bind(&skip); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2470 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 2464 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
| 2471 // Assignment to a property, using a named store IC. | 2465 // Assignment to a property, using a named store IC. |
| 2472 Property* prop = expr->target()->AsProperty(); | 2466 Property* prop = expr->target()->AsProperty(); |
| 2473 ASSERT(prop != NULL); | 2467 ASSERT(prop != NULL); |
| 2474 ASSERT(prop->key()->AsLiteral() != NULL); | 2468 ASSERT(prop->key()->AsLiteral() != NULL); |
| 2475 | 2469 |
| 2476 // Record source code position before IC call. | 2470 // Record source code position before IC call. |
| 2477 SetSourcePosition(expr->position()); | 2471 SetSourcePosition(expr->position()); |
| 2478 __ Move(rcx, prop->key()->AsLiteral()->value()); | 2472 __ Move(rcx, prop->key()->AsLiteral()->value()); |
| 2479 __ pop(rdx); | 2473 __ pop(rdx); |
| 2480 Handle<Code> ic = is_classic_mode() | 2474 CallStoreIC(NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); |
| 2481 ? isolate()->builtins()->StoreIC_Initialize() | |
| 2482 : isolate()->builtins()->StoreIC_Initialize_Strict(); | |
| 2483 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); | |
| 2484 | 2475 |
| 2485 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2476 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2486 context()->Plug(rax); | 2477 context()->Plug(rax); |
| 2487 } | 2478 } |
| 2488 | 2479 |
| 2489 | 2480 |
| 2490 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2481 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 2491 // Assignment to a property, using a keyed store IC. | 2482 // Assignment to a property, using a keyed store IC. |
| 2492 | 2483 |
| 2493 __ pop(rcx); | 2484 __ pop(rcx); |
| 2494 __ pop(rdx); | 2485 __ pop(rdx); |
| 2495 // Record source code position before IC call. | 2486 // Record source code position before IC call. |
| 2496 SetSourcePosition(expr->position()); | 2487 SetSourcePosition(expr->position()); |
| 2497 Handle<Code> ic = is_classic_mode() | 2488 Handle<Code> ic = is_classic_mode() |
| 2498 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2489 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2499 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2490 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2500 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); | 2491 CallIC(ic, NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); |
| 2501 | 2492 |
| 2502 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2493 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2503 context()->Plug(rax); | 2494 context()->Plug(rax); |
| 2504 } | 2495 } |
| 2505 | 2496 |
| 2506 | 2497 |
| 2507 void FullCodeGenerator::VisitProperty(Property* expr) { | 2498 void FullCodeGenerator::VisitProperty(Property* expr) { |
| 2508 Comment cmnt(masm_, "[ Property"); | 2499 Comment cmnt(masm_, "[ Property"); |
| 2509 Expression* key = expr->key(); | 2500 Expression* key = expr->key(); |
| 2510 | 2501 |
| 2511 if (key->IsPropertyName()) { | 2502 if (key->IsPropertyName()) { |
| 2512 VisitForAccumulatorValue(expr->obj()); | 2503 VisitForAccumulatorValue(expr->obj()); |
| 2513 EmitNamedPropertyLoad(expr); | 2504 EmitNamedPropertyLoad(expr); |
| 2514 PrepareForBailoutForId(expr->LoadId(), TOS_REG); | 2505 PrepareForBailoutForId(expr->LoadId(), TOS_REG); |
| 2515 context()->Plug(rax); | 2506 context()->Plug(rax); |
| 2516 } else { | 2507 } else { |
| 2517 VisitForStackValue(expr->obj()); | 2508 VisitForStackValue(expr->obj()); |
| 2518 VisitForAccumulatorValue(expr->key()); | 2509 VisitForAccumulatorValue(expr->key()); |
| 2519 __ pop(rdx); | 2510 __ pop(rdx); |
| 2520 EmitKeyedPropertyLoad(expr); | 2511 EmitKeyedPropertyLoad(expr); |
| 2521 context()->Plug(rax); | 2512 context()->Plug(rax); |
| 2522 } | 2513 } |
| 2523 } | 2514 } |
| 2524 | 2515 |
| 2525 | 2516 |
| 2526 void FullCodeGenerator::CallIC(Handle<Code> code, | 2517 void FullCodeGenerator::CallIC(Handle<Code> code, |
| 2527 RelocInfo::Mode rmode, | 2518 ContextualMode mode, |
| 2528 TypeFeedbackId ast_id) { | 2519 TypeFeedbackId ast_id) { |
| 2529 ic_total_count_++; | 2520 ic_total_count_++; |
| 2530 __ call(code, rmode, ast_id); | 2521 ASSERT(mode != CONTEXTUAL || ast_id.IsNone()); |
| 2522 __ call(code, RelocInfo::CODE_TARGET, ast_id); |
| 2531 } | 2523 } |
| 2532 | 2524 |
| 2533 | 2525 |
| 2534 void FullCodeGenerator::EmitCallWithIC(Call* expr, | 2526 void FullCodeGenerator::EmitCallWithIC(Call* expr, |
| 2535 Handle<Object> name, | 2527 Handle<Object> name, |
| 2536 RelocInfo::Mode mode) { | 2528 ContextualMode mode) { |
| 2537 // Code common for calls using the IC. | 2529 // Code common for calls using the IC. |
| 2538 ZoneList<Expression*>* args = expr->arguments(); | 2530 ZoneList<Expression*>* args = expr->arguments(); |
| 2539 int arg_count = args->length(); | 2531 int arg_count = args->length(); |
| 2540 { PreservePositionScope scope(masm()->positions_recorder()); | 2532 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2541 for (int i = 0; i < arg_count; i++) { | 2533 for (int i = 0; i < arg_count; i++) { |
| 2542 VisitForStackValue(args->at(i)); | 2534 VisitForStackValue(args->at(i)); |
| 2543 } | 2535 } |
| 2544 __ Move(rcx, name); | 2536 __ Move(rcx, name); |
| 2545 } | 2537 } |
| 2546 // Record source position for debugger. | 2538 // Record source position for debugger. |
| 2547 SetSourcePosition(expr->position()); | 2539 SetSourcePosition(expr->position()); |
| 2548 // Call the IC initialization code. | 2540 // Call the IC initialization code. |
| 2549 Handle<Code> ic = | 2541 Handle<Code> ic = |
| 2550 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); | 2542 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); |
| 2551 CallIC(ic, mode, expr->CallFeedbackId()); | 2543 TypeFeedbackId ast_id = mode == CONTEXTUAL |
| 2544 ? TypeFeedbackId::None() |
| 2545 : expr->CallFeedbackId(); |
| 2546 CallIC(ic, mode, ast_id); |
| 2552 RecordJSReturnSite(expr); | 2547 RecordJSReturnSite(expr); |
| 2553 // Restore context register. | 2548 // Restore context register. |
| 2554 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2549 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 2555 context()->Plug(rax); | 2550 context()->Plug(rax); |
| 2556 } | 2551 } |
| 2557 | 2552 |
| 2558 | 2553 |
| 2559 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2554 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
| 2560 Expression* key) { | 2555 Expression* key) { |
| 2561 // Load the key. | 2556 // Load the key. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2574 for (int i = 0; i < arg_count; i++) { | 2569 for (int i = 0; i < arg_count; i++) { |
| 2575 VisitForStackValue(args->at(i)); | 2570 VisitForStackValue(args->at(i)); |
| 2576 } | 2571 } |
| 2577 } | 2572 } |
| 2578 // Record source position for debugger. | 2573 // Record source position for debugger. |
| 2579 SetSourcePosition(expr->position()); | 2574 SetSourcePosition(expr->position()); |
| 2580 // Call the IC initialization code. | 2575 // Call the IC initialization code. |
| 2581 Handle<Code> ic = | 2576 Handle<Code> ic = |
| 2582 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); | 2577 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); |
| 2583 __ movq(rcx, Operand(rsp, (arg_count + 1) * kPointerSize)); // Key. | 2578 __ movq(rcx, Operand(rsp, (arg_count + 1) * kPointerSize)); // Key. |
| 2584 CallIC(ic, RelocInfo::CODE_TARGET, expr->CallFeedbackId()); | 2579 CallIC(ic, NOT_CONTEXTUAL, expr->CallFeedbackId()); |
| 2585 RecordJSReturnSite(expr); | 2580 RecordJSReturnSite(expr); |
| 2586 // Restore context register. | 2581 // Restore context register. |
| 2587 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2582 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 2588 context()->DropAndPlug(1, rax); // Drop the key still on the stack. | 2583 context()->DropAndPlug(1, rax); // Drop the key still on the stack. |
| 2589 } | 2584 } |
| 2590 | 2585 |
| 2591 | 2586 |
| 2592 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { | 2587 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { |
| 2593 // Code common for calls using the call stub. | 2588 // Code common for calls using the call stub. |
| 2594 ZoneList<Expression*>* args = expr->arguments(); | 2589 ZoneList<Expression*>* args = expr->arguments(); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2675 __ push(Operand(rsp, (arg_count + 1) * kPointerSize)); | 2670 __ push(Operand(rsp, (arg_count + 1) * kPointerSize)); |
| 2676 EmitResolvePossiblyDirectEval(arg_count); | 2671 EmitResolvePossiblyDirectEval(arg_count); |
| 2677 | 2672 |
| 2678 // The runtime call returns a pair of values in rax (function) and | 2673 // The runtime call returns a pair of values in rax (function) and |
| 2679 // rdx (receiver). Touch up the stack with the right values. | 2674 // rdx (receiver). Touch up the stack with the right values. |
| 2680 __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx); | 2675 __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx); |
| 2681 __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax); | 2676 __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax); |
| 2682 } | 2677 } |
| 2683 // Record source position for debugger. | 2678 // Record source position for debugger. |
| 2684 SetSourcePosition(expr->position()); | 2679 SetSourcePosition(expr->position()); |
| 2685 CallFunctionStub stub(arg_count, RECEIVER_MIGHT_BE_IMPLICIT); | 2680 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS); |
| 2686 __ movq(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); | 2681 __ movq(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); |
| 2687 __ CallStub(&stub); | 2682 __ CallStub(&stub); |
| 2688 RecordJSReturnSite(expr); | 2683 RecordJSReturnSite(expr); |
| 2689 // Restore context register. | 2684 // Restore context register. |
| 2690 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2685 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 2691 context()->DropAndPlug(1, rax); | 2686 context()->DropAndPlug(1, rax); |
| 2692 } else if (proxy != NULL && proxy->var()->IsUnallocated()) { | 2687 } else if (proxy != NULL && proxy->var()->IsUnallocated()) { |
| 2693 // Call to a global variable. Push global object as receiver for the | 2688 // Call to a global variable. Push global object as receiver for the |
| 2694 // call IC lookup. | 2689 // call IC lookup. |
| 2695 __ push(GlobalObjectOperand()); | 2690 __ push(GlobalObjectOperand()); |
| 2696 EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT); | 2691 EmitCallWithIC(expr, proxy->name(), CONTEXTUAL); |
| 2697 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { | 2692 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { |
| 2698 // Call to a lookup slot (dynamically introduced variable). | 2693 // Call to a lookup slot (dynamically introduced variable). |
| 2699 Label slow, done; | 2694 Label slow, done; |
| 2700 | 2695 |
| 2701 { PreservePositionScope scope(masm()->positions_recorder()); | 2696 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2702 // Generate code for loading from variables potentially shadowed by | 2697 // Generate code for loading from variables potentially shadowed by |
| 2703 // eval-introduced variables. | 2698 // eval-introduced variables. |
| 2704 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); | 2699 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); |
| 2705 } | 2700 } |
| 2706 __ bind(&slow); | 2701 __ bind(&slow); |
| 2707 // Call the runtime to find the function to call (returned in rax) and | 2702 // Call the runtime to find the function to call (returned in rax) and |
| 2708 // the object holding it (returned in rdx). | 2703 // the object holding it (returned in rdx). |
| 2709 __ push(context_register()); | 2704 __ push(context_register()); |
| 2710 __ Push(proxy->name()); | 2705 __ Push(proxy->name()); |
| 2711 __ CallRuntime(Runtime::kLoadContextSlot, 2); | 2706 __ CallRuntime(Runtime::kLoadContextSlot, 2); |
| 2712 __ push(rax); // Function. | 2707 __ push(rax); // Function. |
| 2713 __ push(rdx); // Receiver. | 2708 __ push(rdx); // Receiver. |
| 2714 | 2709 |
| 2715 // If fast case code has been generated, emit code to push the function | 2710 // If fast case code has been generated, emit code to push the function |
| 2716 // and receiver and have the slow path jump around this code. | 2711 // and receiver and have the slow path jump around this code. |
| 2717 if (done.is_linked()) { | 2712 if (done.is_linked()) { |
| 2718 Label call; | 2713 Label call; |
| 2719 __ jmp(&call, Label::kNear); | 2714 __ jmp(&call, Label::kNear); |
| 2720 __ bind(&done); | 2715 __ bind(&done); |
| 2721 // Push function. | 2716 // Push function. |
| 2722 __ push(rax); | 2717 __ push(rax); |
| 2723 // The receiver is implicitly the global receiver. Indicate this by | 2718 // The receiver is implicitly the global receiver. Indicate this by |
| 2724 // passing the hole to the call function stub. | 2719 // passing the hole to the call function stub. |
| 2725 __ PushRoot(Heap::kTheHoleValueRootIndex); | 2720 __ PushRoot(Heap::kUndefinedValueRootIndex); |
| 2726 __ bind(&call); | 2721 __ bind(&call); |
| 2727 } | 2722 } |
| 2728 | 2723 |
| 2729 // The receiver is either the global receiver or an object found by | 2724 // The receiver is either the global receiver or an object found by |
| 2730 // LoadContextSlot. That object could be the hole if the receiver is | 2725 // LoadContextSlot. |
| 2731 // implicitly the global object. | 2726 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); |
| 2732 EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT); | |
| 2733 } else if (property != NULL) { | 2727 } else if (property != NULL) { |
| 2734 { PreservePositionScope scope(masm()->positions_recorder()); | 2728 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2735 VisitForStackValue(property->obj()); | 2729 VisitForStackValue(property->obj()); |
| 2736 } | 2730 } |
| 2737 if (property->key()->IsPropertyName()) { | 2731 if (property->key()->IsPropertyName()) { |
| 2738 EmitCallWithIC(expr, | 2732 EmitCallWithIC(expr, |
| 2739 property->key()->AsLiteral()->value(), | 2733 property->key()->AsLiteral()->value(), |
| 2740 RelocInfo::CODE_TARGET); | 2734 NOT_CONTEXTUAL); |
| 2741 } else { | 2735 } else { |
| 2742 EmitKeyedCallWithIC(expr, property->key()); | 2736 EmitKeyedCallWithIC(expr, property->key()); |
| 2743 } | 2737 } |
| 2744 } else { | 2738 } else { |
| 2745 // Call to an arbitrary expression not handled specially above. | 2739 // Call to an arbitrary expression not handled specially above. |
| 2746 { PreservePositionScope scope(masm()->positions_recorder()); | 2740 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2747 VisitForStackValue(callee); | 2741 VisitForStackValue(callee); |
| 2748 } | 2742 } |
| 2749 // Load global receiver object. | 2743 __ PushRoot(Heap::kUndefinedValueRootIndex); |
| 2750 __ movq(rbx, GlobalObjectOperand()); | |
| 2751 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); | |
| 2752 // Emit function call. | 2744 // Emit function call. |
| 2753 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); | 2745 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); |
| 2754 } | 2746 } |
| 2755 | 2747 |
| 2756 #ifdef DEBUG | 2748 #ifdef DEBUG |
| 2757 // RecordJSReturnSite should have been called. | 2749 // RecordJSReturnSite should have been called. |
| 2758 ASSERT(expr->return_is_recorded_); | 2750 ASSERT(expr->return_is_recorded_); |
| 2759 #endif | 2751 #endif |
| 2760 } | 2752 } |
| 2761 | 2753 |
| (...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3349 __ movq(scratch, stamp_operand); | 3341 __ movq(scratch, stamp_operand); |
| 3350 __ cmpq(scratch, FieldOperand(object, JSDate::kCacheStampOffset)); | 3342 __ cmpq(scratch, FieldOperand(object, JSDate::kCacheStampOffset)); |
| 3351 __ j(not_equal, &runtime, Label::kNear); | 3343 __ j(not_equal, &runtime, Label::kNear); |
| 3352 __ movq(result, FieldOperand(object, JSDate::kValueOffset + | 3344 __ movq(result, FieldOperand(object, JSDate::kValueOffset + |
| 3353 kPointerSize * index->value())); | 3345 kPointerSize * index->value())); |
| 3354 __ jmp(&done); | 3346 __ jmp(&done); |
| 3355 } | 3347 } |
| 3356 __ bind(&runtime); | 3348 __ bind(&runtime); |
| 3357 __ PrepareCallCFunction(2); | 3349 __ PrepareCallCFunction(2); |
| 3358 __ movq(arg_reg_1, object); | 3350 __ movq(arg_reg_1, object); |
| 3359 __ movq(arg_reg_2, index, RelocInfo::NONE64); | 3351 __ Move(arg_reg_2, index, RelocInfo::NONE64); |
| 3360 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); | 3352 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); |
| 3361 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 3353 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 3362 __ jmp(&done); | 3354 __ jmp(&done); |
| 3363 } | 3355 } |
| 3364 | 3356 |
| 3365 __ bind(¬_date_object); | 3357 __ bind(¬_date_object); |
| 3366 __ CallRuntime(Runtime::kThrowNotDateError, 0); | 3358 __ CallRuntime(Runtime::kThrowNotDateError, 0); |
| 3367 __ bind(&done); | 3359 __ bind(&done); |
| 3368 context()->Plug(rax); | 3360 context()->Plug(rax); |
| 3369 } | 3361 } |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3669 Label runtime, done; | 3661 Label runtime, done; |
| 3670 // Check for non-function argument (including proxy). | 3662 // Check for non-function argument (including proxy). |
| 3671 __ JumpIfSmi(rax, &runtime); | 3663 __ JumpIfSmi(rax, &runtime); |
| 3672 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); | 3664 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); |
| 3673 __ j(not_equal, &runtime); | 3665 __ j(not_equal, &runtime); |
| 3674 | 3666 |
| 3675 // InvokeFunction requires the function in rdi. Move it in there. | 3667 // InvokeFunction requires the function in rdi. Move it in there. |
| 3676 __ movq(rdi, result_register()); | 3668 __ movq(rdi, result_register()); |
| 3677 ParameterCount count(arg_count); | 3669 ParameterCount count(arg_count); |
| 3678 __ InvokeFunction(rdi, count, CALL_FUNCTION, | 3670 __ InvokeFunction(rdi, count, CALL_FUNCTION, |
| 3679 NullCallWrapper(), CALL_AS_METHOD); | 3671 NullCallWrapper(), CALL_AS_FUNCTION); |
| 3680 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 3672 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 3681 __ jmp(&done); | 3673 __ jmp(&done); |
| 3682 | 3674 |
| 3683 __ bind(&runtime); | 3675 __ bind(&runtime); |
| 3684 __ push(rax); | 3676 __ push(rax); |
| 3685 __ CallRuntime(Runtime::kCall, args->length()); | 3677 __ CallRuntime(Runtime::kCall, args->length()); |
| 3686 __ bind(&done); | 3678 __ bind(&done); |
| 3687 | 3679 |
| 3688 context()->Plug(rax); | 3680 context()->Plug(rax); |
| 3689 } | 3681 } |
| (...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4139 | 4131 |
| 4140 // Push the arguments ("left-to-right"). | 4132 // Push the arguments ("left-to-right"). |
| 4141 int arg_count = args->length(); | 4133 int arg_count = args->length(); |
| 4142 for (int i = 0; i < arg_count; i++) { | 4134 for (int i = 0; i < arg_count; i++) { |
| 4143 VisitForStackValue(args->at(i)); | 4135 VisitForStackValue(args->at(i)); |
| 4144 } | 4136 } |
| 4145 | 4137 |
| 4146 if (expr->is_jsruntime()) { | 4138 if (expr->is_jsruntime()) { |
| 4147 // Call the JS runtime function using a call IC. | 4139 // Call the JS runtime function using a call IC. |
| 4148 __ Move(rcx, expr->name()); | 4140 __ Move(rcx, expr->name()); |
| 4149 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; | 4141 ContextualMode mode = NOT_CONTEXTUAL; |
| 4150 Handle<Code> ic = | 4142 Handle<Code> ic = |
| 4151 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); | 4143 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); |
| 4152 CallIC(ic, mode, expr->CallRuntimeFeedbackId()); | 4144 CallIC(ic, mode, expr->CallRuntimeFeedbackId()); |
| 4153 // Restore context register. | 4145 // Restore context register. |
| 4154 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 4146 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 4155 } else { | 4147 } else { |
| 4156 __ CallRuntime(expr->function(), arg_count); | 4148 __ CallRuntime(expr->function(), arg_count); |
| 4157 } | 4149 } |
| 4158 context()->Plug(rax); | 4150 context()->Plug(rax); |
| 4159 } | 4151 } |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4393 | 4385 |
| 4394 // Record position before stub call. | 4386 // Record position before stub call. |
| 4395 SetSourcePosition(expr->position()); | 4387 SetSourcePosition(expr->position()); |
| 4396 | 4388 |
| 4397 // Call stub for +1/-1. | 4389 // Call stub for +1/-1. |
| 4398 __ bind(&stub_call); | 4390 __ bind(&stub_call); |
| 4399 __ movq(rdx, rax); | 4391 __ movq(rdx, rax); |
| 4400 __ Move(rax, Smi::FromInt(1)); | 4392 __ Move(rax, Smi::FromInt(1)); |
| 4401 BinaryOpICStub stub(expr->binary_op(), NO_OVERWRITE); | 4393 BinaryOpICStub stub(expr->binary_op(), NO_OVERWRITE); |
| 4402 CallIC(stub.GetCode(isolate()), | 4394 CallIC(stub.GetCode(isolate()), |
| 4403 RelocInfo::CODE_TARGET, | 4395 NOT_CONTEXTUAL, |
| 4404 expr->CountBinOpFeedbackId()); | 4396 expr->CountBinOpFeedbackId()); |
| 4405 patch_site.EmitPatchInfo(); | 4397 patch_site.EmitPatchInfo(); |
| 4406 __ bind(&done); | 4398 __ bind(&done); |
| 4407 | 4399 |
| 4408 // Store the value returned in rax. | 4400 // Store the value returned in rax. |
| 4409 switch (assign_type) { | 4401 switch (assign_type) { |
| 4410 case VARIABLE: | 4402 case VARIABLE: |
| 4411 if (expr->is_postfix()) { | 4403 if (expr->is_postfix()) { |
| 4412 // Perform the assignment as if via '='. | 4404 // Perform the assignment as if via '='. |
| 4413 { EffectContext context(this); | 4405 { EffectContext context(this); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 4425 // Perform the assignment as if via '='. | 4417 // Perform the assignment as if via '='. |
| 4426 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 4418 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 4427 Token::ASSIGN); | 4419 Token::ASSIGN); |
| 4428 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4420 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4429 context()->Plug(rax); | 4421 context()->Plug(rax); |
| 4430 } | 4422 } |
| 4431 break; | 4423 break; |
| 4432 case NAMED_PROPERTY: { | 4424 case NAMED_PROPERTY: { |
| 4433 __ Move(rcx, prop->key()->AsLiteral()->value()); | 4425 __ Move(rcx, prop->key()->AsLiteral()->value()); |
| 4434 __ pop(rdx); | 4426 __ pop(rdx); |
| 4435 Handle<Code> ic = is_classic_mode() | 4427 CallStoreIC(NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); |
| 4436 ? isolate()->builtins()->StoreIC_Initialize() | |
| 4437 : isolate()->builtins()->StoreIC_Initialize_Strict(); | |
| 4438 CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); | |
| 4439 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4428 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4440 if (expr->is_postfix()) { | 4429 if (expr->is_postfix()) { |
| 4441 if (!context()->IsEffect()) { | 4430 if (!context()->IsEffect()) { |
| 4442 context()->PlugTOS(); | 4431 context()->PlugTOS(); |
| 4443 } | 4432 } |
| 4444 } else { | 4433 } else { |
| 4445 context()->Plug(rax); | 4434 context()->Plug(rax); |
| 4446 } | 4435 } |
| 4447 break; | 4436 break; |
| 4448 } | 4437 } |
| 4449 case KEYED_PROPERTY: { | 4438 case KEYED_PROPERTY: { |
| 4450 __ pop(rcx); | 4439 __ pop(rcx); |
| 4451 __ pop(rdx); | 4440 __ pop(rdx); |
| 4452 Handle<Code> ic = is_classic_mode() | 4441 Handle<Code> ic = is_classic_mode() |
| 4453 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 4442 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 4454 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 4443 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 4455 CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); | 4444 CallIC(ic, NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); |
| 4456 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4445 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4457 if (expr->is_postfix()) { | 4446 if (expr->is_postfix()) { |
| 4458 if (!context()->IsEffect()) { | 4447 if (!context()->IsEffect()) { |
| 4459 context()->PlugTOS(); | 4448 context()->PlugTOS(); |
| 4460 } | 4449 } |
| 4461 } else { | 4450 } else { |
| 4462 context()->Plug(rax); | 4451 context()->Plug(rax); |
| 4463 } | 4452 } |
| 4464 break; | 4453 break; |
| 4465 } | 4454 } |
| 4466 } | 4455 } |
| 4467 } | 4456 } |
| 4468 | 4457 |
| 4469 | 4458 |
| 4470 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | 4459 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { |
| 4471 VariableProxy* proxy = expr->AsVariableProxy(); | 4460 VariableProxy* proxy = expr->AsVariableProxy(); |
| 4472 ASSERT(!context()->IsEffect()); | 4461 ASSERT(!context()->IsEffect()); |
| 4473 ASSERT(!context()->IsTest()); | 4462 ASSERT(!context()->IsTest()); |
| 4474 | 4463 |
| 4475 if (proxy != NULL && proxy->var()->IsUnallocated()) { | 4464 if (proxy != NULL && proxy->var()->IsUnallocated()) { |
| 4476 Comment cmnt(masm_, "Global variable"); | 4465 Comment cmnt(masm_, "Global variable"); |
| 4477 __ Move(rcx, proxy->name()); | 4466 __ Move(rcx, proxy->name()); |
| 4478 __ movq(rax, GlobalObjectOperand()); | 4467 __ movq(rax, GlobalObjectOperand()); |
| 4479 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | |
| 4480 // Use a regular load, not a contextual load, to avoid a reference | 4468 // Use a regular load, not a contextual load, to avoid a reference |
| 4481 // error. | 4469 // error. |
| 4482 CallIC(ic); | 4470 CallLoadIC(NOT_CONTEXTUAL); |
| 4483 PrepareForBailout(expr, TOS_REG); | 4471 PrepareForBailout(expr, TOS_REG); |
| 4484 context()->Plug(rax); | 4472 context()->Plug(rax); |
| 4485 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { | 4473 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { |
| 4486 Label done, slow; | 4474 Label done, slow; |
| 4487 | 4475 |
| 4488 // Generate code for loading from variables potentially shadowed | 4476 // Generate code for loading from variables potentially shadowed |
| 4489 // by eval-introduced variables. | 4477 // by eval-introduced variables. |
| 4490 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); | 4478 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); |
| 4491 | 4479 |
| 4492 __ bind(&slow); | 4480 __ bind(&slow); |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4634 __ or_(rcx, rax); | 4622 __ or_(rcx, rax); |
| 4635 patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear); | 4623 patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear); |
| 4636 __ cmpq(rdx, rax); | 4624 __ cmpq(rdx, rax); |
| 4637 Split(cc, if_true, if_false, NULL); | 4625 Split(cc, if_true, if_false, NULL); |
| 4638 __ bind(&slow_case); | 4626 __ bind(&slow_case); |
| 4639 } | 4627 } |
| 4640 | 4628 |
| 4641 // Record position and call the compare IC. | 4629 // Record position and call the compare IC. |
| 4642 SetSourcePosition(expr->position()); | 4630 SetSourcePosition(expr->position()); |
| 4643 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 4631 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
| 4644 CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); | 4632 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); |
| 4645 patch_site.EmitPatchInfo(); | 4633 patch_site.EmitPatchInfo(); |
| 4646 | 4634 |
| 4647 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 4635 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 4648 __ testq(rax, rax); | 4636 __ testq(rax, rax); |
| 4649 Split(cc, if_true, if_false, fall_through); | 4637 Split(cc, if_true, if_false, fall_through); |
| 4650 } | 4638 } |
| 4651 } | 4639 } |
| 4652 | 4640 |
| 4653 // Convert the result of the comparison into one expected for this | 4641 // Convert the result of the comparison into one expected for this |
| 4654 // expression's context. | 4642 // expression's context. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4669 VisitForAccumulatorValue(sub_expr); | 4657 VisitForAccumulatorValue(sub_expr); |
| 4670 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 4658 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 4671 if (expr->op() == Token::EQ_STRICT) { | 4659 if (expr->op() == Token::EQ_STRICT) { |
| 4672 Heap::RootListIndex nil_value = nil == kNullValue ? | 4660 Heap::RootListIndex nil_value = nil == kNullValue ? |
| 4673 Heap::kNullValueRootIndex : | 4661 Heap::kNullValueRootIndex : |
| 4674 Heap::kUndefinedValueRootIndex; | 4662 Heap::kUndefinedValueRootIndex; |
| 4675 __ CompareRoot(rax, nil_value); | 4663 __ CompareRoot(rax, nil_value); |
| 4676 Split(equal, if_true, if_false, fall_through); | 4664 Split(equal, if_true, if_false, fall_through); |
| 4677 } else { | 4665 } else { |
| 4678 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); | 4666 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); |
| 4679 CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); | 4667 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); |
| 4680 __ testq(rax, rax); | 4668 __ testq(rax, rax); |
| 4681 Split(not_zero, if_true, if_false, fall_through); | 4669 Split(not_zero, if_true, if_false, fall_through); |
| 4682 } | 4670 } |
| 4683 context()->Plug(if_true, if_false); | 4671 context()->Plug(if_true, if_false); |
| 4684 } | 4672 } |
| 4685 | 4673 |
| 4686 | 4674 |
| 4687 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 4675 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
| 4688 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 4676 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
| 4689 context()->Plug(rax); | 4677 context()->Plug(rax); |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4901 | 4889 |
| 4902 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), | 4890 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), |
| 4903 Assembler::target_address_at(call_target_address)); | 4891 Assembler::target_address_at(call_target_address)); |
| 4904 return OSR_AFTER_STACK_CHECK; | 4892 return OSR_AFTER_STACK_CHECK; |
| 4905 } | 4893 } |
| 4906 | 4894 |
| 4907 | 4895 |
| 4908 } } // namespace v8::internal | 4896 } } // namespace v8::internal |
| 4909 | 4897 |
| 4910 #endif // V8_TARGET_ARCH_X64 | 4898 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |