| 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 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 | 137 |
| 138 ProfileEntryHookStub::MaybeCallEntryHook(masm_); | 138 ProfileEntryHookStub::MaybeCallEntryHook(masm_); |
| 139 | 139 |
| 140 #ifdef DEBUG | 140 #ifdef DEBUG |
| 141 if (strlen(FLAG_stop_at) > 0 && | 141 if (strlen(FLAG_stop_at) > 0 && |
| 142 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { | 142 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { |
| 143 __ stop("stop-at"); | 143 __ stop("stop-at"); |
| 144 } | 144 } |
| 145 #endif | 145 #endif |
| 146 | 146 |
| 147 // Strict mode functions and builtins need to replace the receiver | 147 // Classic mode functions and builtins need to replace the receiver with the |
| 148 // with undefined when called as functions (without an explicit | 148 // global proxy when called as functions (without an explicit receiver |
| 149 // receiver object). r5 is zero for method calls and non-zero for | 149 // object). |
| 150 // function calls. | 150 if (info->is_classic_mode() && !info->is_native()) { |
| 151 if (!info->is_classic_mode() || info->is_native()) { | 151 Label ok; |
| 152 __ cmp(r5, Operand::Zero()); | 152 __ cmp(r5, Operand::Zero()); |
| 153 __ b(eq, &ok); |
| 154 |
| 153 int receiver_offset = info->scope()->num_parameters() * kPointerSize; | 155 int receiver_offset = info->scope()->num_parameters() * kPointerSize; |
| 154 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); | 156 __ ldr(r2, MemOperand(sp, receiver_offset)); |
| 155 __ str(r2, MemOperand(sp, receiver_offset), ne); | 157 __ CompareRoot(r2, Heap::kUndefinedValueRootIndex); |
| 158 __ b(ne, &ok); |
| 159 |
| 160 __ ldr(r2, GlobalObjectOperand()); |
| 161 __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset)); |
| 162 |
| 163 __ str(r2, MemOperand(sp, receiver_offset)); |
| 164 |
| 165 __ bind(&ok); |
| 156 } | 166 } |
| 157 | 167 |
| 158 // Open a frame scope to indicate that there is a frame on the stack. The | 168 // Open a frame scope to indicate that there is a frame on the stack. The |
| 159 // MANUAL indicates that the scope shouldn't actually generate code to set up | 169 // MANUAL indicates that the scope shouldn't actually generate code to set up |
| 160 // the frame (that is done below). | 170 // the frame (that is done below). |
| 161 FrameScope frame_scope(masm_, StackFrame::MANUAL); | 171 FrameScope frame_scope(masm_, StackFrame::MANUAL); |
| 162 | 172 |
| 163 info->set_prologue_offset(masm_->pc_offset()); | 173 info->set_prologue_offset(masm_->pc_offset()); |
| 164 __ Prologue(BUILD_FUNCTION_FRAME); | 174 __ Prologue(BUILD_FUNCTION_FRAME); |
| 165 info->AddNoFrameRange(0, masm_->pc_offset()); | 175 info->AddNoFrameRange(0, masm_->pc_offset()); |
| (...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 652 if (false_label_ != fall_through_) __ b(false_label_); | 662 if (false_label_ != fall_through_) __ b(false_label_); |
| 653 } | 663 } |
| 654 } | 664 } |
| 655 | 665 |
| 656 | 666 |
| 657 void FullCodeGenerator::DoTest(Expression* condition, | 667 void FullCodeGenerator::DoTest(Expression* condition, |
| 658 Label* if_true, | 668 Label* if_true, |
| 659 Label* if_false, | 669 Label* if_false, |
| 660 Label* fall_through) { | 670 Label* fall_through) { |
| 661 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); | 671 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); |
| 662 CallIC(ic, RelocInfo::CODE_TARGET, condition->test_id()); | 672 CallIC(ic, NOT_CONTEXTUAL, condition->test_id()); |
| 663 __ tst(result_register(), result_register()); | 673 __ tst(result_register(), result_register()); |
| 664 Split(ne, if_true, if_false, fall_through); | 674 Split(ne, if_true, if_false, fall_through); |
| 665 } | 675 } |
| 666 | 676 |
| 667 | 677 |
| 668 void FullCodeGenerator::Split(Condition cond, | 678 void FullCodeGenerator::Split(Condition cond, |
| 669 Label* if_true, | 679 Label* if_true, |
| 670 Label* if_false, | 680 Label* if_false, |
| 671 Label* fall_through) { | 681 Label* fall_through) { |
| 672 if (if_false == fall_through) { | 682 if (if_false == fall_through) { |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1013 __ cmp(r1, r0); | 1023 __ cmp(r1, r0); |
| 1014 __ b(ne, &next_test); | 1024 __ b(ne, &next_test); |
| 1015 __ Drop(1); // Switch value is no longer needed. | 1025 __ Drop(1); // Switch value is no longer needed. |
| 1016 __ b(clause->body_target()); | 1026 __ b(clause->body_target()); |
| 1017 __ bind(&slow_case); | 1027 __ bind(&slow_case); |
| 1018 } | 1028 } |
| 1019 | 1029 |
| 1020 // Record position before stub call for type feedback. | 1030 // Record position before stub call for type feedback. |
| 1021 SetSourcePosition(clause->position()); | 1031 SetSourcePosition(clause->position()); |
| 1022 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); | 1032 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); |
| 1023 CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId()); | 1033 CallIC(ic, NOT_CONTEXTUAL, clause->CompareId()); |
| 1024 patch_site.EmitPatchInfo(); | 1034 patch_site.EmitPatchInfo(); |
| 1025 | 1035 |
| 1026 Label skip; | 1036 Label skip; |
| 1027 __ b(&skip); | 1037 __ b(&skip); |
| 1028 PrepareForBailout(clause, TOS_REG); | 1038 PrepareForBailout(clause, TOS_REG); |
| 1029 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 1039 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
| 1030 __ cmp(r0, ip); | 1040 __ cmp(r0, ip); |
| 1031 __ b(ne, &next_test); | 1041 __ b(ne, &next_test); |
| 1032 __ Drop(1); | 1042 __ Drop(1); |
| 1033 __ jmp(clause->body_target()); | 1043 __ jmp(clause->body_target()); |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1381 __ tst(temp, temp); | 1391 __ tst(temp, temp); |
| 1382 __ b(ne, slow); | 1392 __ b(ne, slow); |
| 1383 // Load next context in chain. | 1393 // Load next context in chain. |
| 1384 __ ldr(next, ContextOperand(next, Context::PREVIOUS_INDEX)); | 1394 __ ldr(next, ContextOperand(next, Context::PREVIOUS_INDEX)); |
| 1385 __ b(&loop); | 1395 __ b(&loop); |
| 1386 __ bind(&fast); | 1396 __ bind(&fast); |
| 1387 } | 1397 } |
| 1388 | 1398 |
| 1389 __ ldr(r0, GlobalObjectOperand()); | 1399 __ ldr(r0, GlobalObjectOperand()); |
| 1390 __ mov(r2, Operand(var->name())); | 1400 __ mov(r2, Operand(var->name())); |
| 1391 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) | 1401 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) |
| 1392 ? RelocInfo::CODE_TARGET | 1402 ? NOT_CONTEXTUAL |
| 1393 : RelocInfo::CODE_TARGET_CONTEXT; | 1403 : CONTEXTUAL; |
| 1394 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1404 CallLoadIC(mode); |
| 1395 CallIC(ic, mode); | |
| 1396 } | 1405 } |
| 1397 | 1406 |
| 1398 | 1407 |
| 1399 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1408 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
| 1400 Label* slow) { | 1409 Label* slow) { |
| 1401 ASSERT(var->IsContextSlot()); | 1410 ASSERT(var->IsContextSlot()); |
| 1402 Register context = cp; | 1411 Register context = cp; |
| 1403 Register next = r3; | 1412 Register next = r3; |
| 1404 Register temp = r4; | 1413 Register temp = r4; |
| 1405 | 1414 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1468 | 1477 |
| 1469 // Three cases: global variables, lookup variables, and all other types of | 1478 // Three cases: global variables, lookup variables, and all other types of |
| 1470 // variables. | 1479 // variables. |
| 1471 switch (var->location()) { | 1480 switch (var->location()) { |
| 1472 case Variable::UNALLOCATED: { | 1481 case Variable::UNALLOCATED: { |
| 1473 Comment cmnt(masm_, "Global variable"); | 1482 Comment cmnt(masm_, "Global variable"); |
| 1474 // Use inline caching. Variable name is passed in r2 and the global | 1483 // Use inline caching. Variable name is passed in r2 and the global |
| 1475 // object (receiver) in r0. | 1484 // object (receiver) in r0. |
| 1476 __ ldr(r0, GlobalObjectOperand()); | 1485 __ ldr(r0, GlobalObjectOperand()); |
| 1477 __ mov(r2, Operand(var->name())); | 1486 __ mov(r2, Operand(var->name())); |
| 1478 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1487 CallLoadIC(CONTEXTUAL); |
| 1479 CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); | |
| 1480 context()->Plug(r0); | 1488 context()->Plug(r0); |
| 1481 break; | 1489 break; |
| 1482 } | 1490 } |
| 1483 | 1491 |
| 1484 case Variable::PARAMETER: | 1492 case Variable::PARAMETER: |
| 1485 case Variable::LOCAL: | 1493 case Variable::LOCAL: |
| 1486 case Variable::CONTEXT: { | 1494 case Variable::CONTEXT: { |
| 1487 Comment cmnt(masm_, var->IsContextSlot() | 1495 Comment cmnt(masm_, var->IsContextSlot() |
| 1488 ? "Context variable" | 1496 ? "Context variable" |
| 1489 : "Stack variable"); | 1497 : "Stack variable"); |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1678 UNREACHABLE(); | 1686 UNREACHABLE(); |
| 1679 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1687 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1680 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); | 1688 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); |
| 1681 // Fall through. | 1689 // Fall through. |
| 1682 case ObjectLiteral::Property::COMPUTED: | 1690 case ObjectLiteral::Property::COMPUTED: |
| 1683 if (key->value()->IsInternalizedString()) { | 1691 if (key->value()->IsInternalizedString()) { |
| 1684 if (property->emit_store()) { | 1692 if (property->emit_store()) { |
| 1685 VisitForAccumulatorValue(value); | 1693 VisitForAccumulatorValue(value); |
| 1686 __ mov(r2, Operand(key->value())); | 1694 __ mov(r2, Operand(key->value())); |
| 1687 __ ldr(r1, MemOperand(sp)); | 1695 __ ldr(r1, MemOperand(sp)); |
| 1688 Handle<Code> ic = is_classic_mode() | 1696 CallStoreIC(NOT_CONTEXTUAL, key->LiteralFeedbackId()); |
| 1689 ? isolate()->builtins()->StoreIC_Initialize() | |
| 1690 : isolate()->builtins()->StoreIC_Initialize_Strict(); | |
| 1691 CallIC(ic, RelocInfo::CODE_TARGET, key->LiteralFeedbackId()); | |
| 1692 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1697 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
| 1693 } else { | 1698 } else { |
| 1694 VisitForEffect(value); | 1699 VisitForEffect(value); |
| 1695 } | 1700 } |
| 1696 break; | 1701 break; |
| 1697 } | 1702 } |
| 1698 // Duplicate receiver on stack. | 1703 // Duplicate receiver on stack. |
| 1699 __ ldr(r0, MemOperand(sp)); | 1704 __ ldr(r0, MemOperand(sp)); |
| 1700 __ push(r0); | 1705 __ push(r0); |
| 1701 VisitForStackValue(key); | 1706 VisitForStackValue(key); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1770 ZoneList<Expression*>* subexprs = expr->values(); | 1775 ZoneList<Expression*>* subexprs = expr->values(); |
| 1771 int length = subexprs->length(); | 1776 int length = subexprs->length(); |
| 1772 Handle<FixedArray> constant_elements = expr->constant_elements(); | 1777 Handle<FixedArray> constant_elements = expr->constant_elements(); |
| 1773 ASSERT_EQ(2, constant_elements->length()); | 1778 ASSERT_EQ(2, constant_elements->length()); |
| 1774 ElementsKind constant_elements_kind = | 1779 ElementsKind constant_elements_kind = |
| 1775 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); | 1780 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); |
| 1776 bool has_fast_elements = IsFastObjectElementsKind(constant_elements_kind); | 1781 bool has_fast_elements = IsFastObjectElementsKind(constant_elements_kind); |
| 1777 Handle<FixedArrayBase> constant_elements_values( | 1782 Handle<FixedArrayBase> constant_elements_values( |
| 1778 FixedArrayBase::cast(constant_elements->get(1))); | 1783 FixedArrayBase::cast(constant_elements->get(1))); |
| 1779 | 1784 |
| 1780 AllocationSiteMode allocation_site_mode = FLAG_track_allocation_sites | 1785 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE; |
| 1781 ? TRACK_ALLOCATION_SITE : DONT_TRACK_ALLOCATION_SITE; | |
| 1782 if (has_fast_elements && !FLAG_allocation_site_pretenuring) { | 1786 if (has_fast_elements && !FLAG_allocation_site_pretenuring) { |
| 1783 // If the only customer of allocation sites is transitioning, then | 1787 // If the only customer of allocation sites is transitioning, then |
| 1784 // we can turn it off if we don't have anywhere else to transition to. | 1788 // we can turn it off if we don't have anywhere else to transition to. |
| 1785 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; | 1789 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; |
| 1786 } | 1790 } |
| 1787 | 1791 |
| 1788 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1792 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1789 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); | 1793 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); |
| 1790 __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); | 1794 __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); |
| 1791 __ mov(r1, Operand(constant_elements)); | 1795 __ mov(r1, Operand(constant_elements)); |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2089 // result = receiver[f](arg); | 2093 // result = receiver[f](arg); |
| 2090 __ bind(&l_call); | 2094 __ bind(&l_call); |
| 2091 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); | 2095 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); |
| 2092 CallIC(ic); | 2096 CallIC(ic); |
| 2093 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2097 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2094 | 2098 |
| 2095 // if (!result.done) goto l_try; | 2099 // if (!result.done) goto l_try; |
| 2096 __ bind(&l_loop); | 2100 __ bind(&l_loop); |
| 2097 __ push(r0); // save result | 2101 __ push(r0); // save result |
| 2098 __ LoadRoot(r2, Heap::kdone_stringRootIndex); // "done" | 2102 __ LoadRoot(r2, Heap::kdone_stringRootIndex); // "done" |
| 2099 Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize(); | 2103 CallLoadIC(NOT_CONTEXTUAL); // result.done in r0 |
| 2100 CallIC(done_ic); // result.done in r0 | |
| 2101 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); | 2104 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); |
| 2102 CallIC(bool_ic); | 2105 CallIC(bool_ic); |
| 2103 __ cmp(r0, Operand(0)); | 2106 __ cmp(r0, Operand(0)); |
| 2104 __ b(eq, &l_try); | 2107 __ b(eq, &l_try); |
| 2105 | 2108 |
| 2106 // result.value | 2109 // result.value |
| 2107 __ pop(r0); // result | 2110 __ pop(r0); // result |
| 2108 __ LoadRoot(r2, Heap::kvalue_stringRootIndex); // "value" | 2111 __ LoadRoot(r2, Heap::kvalue_stringRootIndex); // "value" |
| 2109 Handle<Code> value_ic = isolate()->builtins()->LoadIC_Initialize(); | 2112 CallLoadIC(NOT_CONTEXTUAL); // result.value in r0 |
| 2110 CallIC(value_ic); // result.value in r0 | |
| 2111 context()->DropAndPlug(2, r0); // drop iter and g | 2113 context()->DropAndPlug(2, r0); // drop iter and g |
| 2112 break; | 2114 break; |
| 2113 } | 2115 } |
| 2114 } | 2116 } |
| 2115 } | 2117 } |
| 2116 | 2118 |
| 2117 | 2119 |
| 2118 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, | 2120 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, |
| 2119 Expression *value, | 2121 Expression *value, |
| 2120 JSGeneratorObject::ResumeMode resume_mode) { | 2122 JSGeneratorObject::ResumeMode resume_mode) { |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2250 __ RecordWriteField(r0, JSGeneratorObject::kResultValuePropertyOffset, | 2252 __ RecordWriteField(r0, JSGeneratorObject::kResultValuePropertyOffset, |
| 2251 r2, r3, kLRHasBeenSaved, kDontSaveFPRegs); | 2253 r2, r3, kLRHasBeenSaved, kDontSaveFPRegs); |
| 2252 } | 2254 } |
| 2253 | 2255 |
| 2254 | 2256 |
| 2255 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 2257 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
| 2256 SetSourcePosition(prop->position()); | 2258 SetSourcePosition(prop->position()); |
| 2257 Literal* key = prop->key()->AsLiteral(); | 2259 Literal* key = prop->key()->AsLiteral(); |
| 2258 __ mov(r2, Operand(key->value())); | 2260 __ mov(r2, Operand(key->value())); |
| 2259 // Call load IC. It has arguments receiver and property name r0 and r2. | 2261 // Call load IC. It has arguments receiver and property name r0 and r2. |
| 2260 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2262 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); |
| 2261 CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); | |
| 2262 } | 2263 } |
| 2263 | 2264 |
| 2264 | 2265 |
| 2265 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 2266 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
| 2266 SetSourcePosition(prop->position()); | 2267 SetSourcePosition(prop->position()); |
| 2267 // Call keyed load IC. It has arguments key and receiver in r0 and r1. | 2268 // Call keyed load IC. It has arguments key and receiver in r0 and r1. |
| 2268 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2269 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 2269 CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); | 2270 CallIC(ic, NOT_CONTEXTUAL, prop->PropertyFeedbackId()); |
| 2270 } | 2271 } |
| 2271 | 2272 |
| 2272 | 2273 |
| 2273 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 2274 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
| 2274 Token::Value op, | 2275 Token::Value op, |
| 2275 OverwriteMode mode, | 2276 OverwriteMode mode, |
| 2276 Expression* left_expr, | 2277 Expression* left_expr, |
| 2277 Expression* right_expr) { | 2278 Expression* right_expr) { |
| 2278 Label done, smi_case, stub_call; | 2279 Label done, smi_case, stub_call; |
| 2279 | 2280 |
| 2280 Register scratch1 = r2; | 2281 Register scratch1 = r2; |
| 2281 Register scratch2 = r3; | 2282 Register scratch2 = r3; |
| 2282 | 2283 |
| 2283 // Get the arguments. | 2284 // Get the arguments. |
| 2284 Register left = r1; | 2285 Register left = r1; |
| 2285 Register right = r0; | 2286 Register right = r0; |
| 2286 __ pop(left); | 2287 __ pop(left); |
| 2287 | 2288 |
| 2288 // Perform combined smi check on both operands. | 2289 // Perform combined smi check on both operands. |
| 2289 __ orr(scratch1, left, Operand(right)); | 2290 __ orr(scratch1, left, Operand(right)); |
| 2290 STATIC_ASSERT(kSmiTag == 0); | 2291 STATIC_ASSERT(kSmiTag == 0); |
| 2291 JumpPatchSite patch_site(masm_); | 2292 JumpPatchSite patch_site(masm_); |
| 2292 patch_site.EmitJumpIfSmi(scratch1, &smi_case); | 2293 patch_site.EmitJumpIfSmi(scratch1, &smi_case); |
| 2293 | 2294 |
| 2294 __ bind(&stub_call); | 2295 __ bind(&stub_call); |
| 2295 BinaryOpICStub stub(op, mode); | 2296 BinaryOpICStub stub(op, mode); |
| 2296 CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, | 2297 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, |
| 2297 expr->BinaryOperationFeedbackId()); | 2298 expr->BinaryOperationFeedbackId()); |
| 2298 patch_site.EmitPatchInfo(); | 2299 patch_site.EmitPatchInfo(); |
| 2299 __ jmp(&done); | 2300 __ jmp(&done); |
| 2300 | 2301 |
| 2301 __ bind(&smi_case); | 2302 __ bind(&smi_case); |
| 2302 // Smi case. This code works the same way as the smi-smi case in the type | 2303 // Smi case. This code works the same way as the smi-smi case in the type |
| 2303 // recording binary operation stub, see | 2304 // recording binary operation stub, see |
| 2304 switch (op) { | 2305 switch (op) { |
| 2305 case Token::SAR: | 2306 case Token::SAR: |
| 2306 __ GetLeastBitsFromSmi(scratch1, right, 5); | 2307 __ GetLeastBitsFromSmi(scratch1, right, 5); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2364 context()->Plug(r0); | 2365 context()->Plug(r0); |
| 2365 } | 2366 } |
| 2366 | 2367 |
| 2367 | 2368 |
| 2368 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, | 2369 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, |
| 2369 Token::Value op, | 2370 Token::Value op, |
| 2370 OverwriteMode mode) { | 2371 OverwriteMode mode) { |
| 2371 __ pop(r1); | 2372 __ pop(r1); |
| 2372 BinaryOpICStub stub(op, mode); | 2373 BinaryOpICStub stub(op, mode); |
| 2373 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 2374 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
| 2374 CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, | 2375 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, |
| 2375 expr->BinaryOperationFeedbackId()); | 2376 expr->BinaryOperationFeedbackId()); |
| 2376 patch_site.EmitPatchInfo(); | 2377 patch_site.EmitPatchInfo(); |
| 2377 context()->Plug(r0); | 2378 context()->Plug(r0); |
| 2378 } | 2379 } |
| 2379 | 2380 |
| 2380 | 2381 |
| 2381 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 2382 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
| 2382 // Invalid left-hand sides are rewritten by the parser to have a 'throw | 2383 // Invalid left-hand sides are rewritten by the parser to have a 'throw |
| 2383 // ReferenceError' on the left-hand side. | 2384 // ReferenceError' on the left-hand side. |
| 2384 if (!expr->IsValidLeftHandSide()) { | 2385 if (!expr->IsValidLeftHandSide()) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2403 EffectContext context(this); | 2404 EffectContext context(this); |
| 2404 EmitVariableAssignment(var, Token::ASSIGN); | 2405 EmitVariableAssignment(var, Token::ASSIGN); |
| 2405 break; | 2406 break; |
| 2406 } | 2407 } |
| 2407 case NAMED_PROPERTY: { | 2408 case NAMED_PROPERTY: { |
| 2408 __ push(r0); // Preserve value. | 2409 __ push(r0); // Preserve value. |
| 2409 VisitForAccumulatorValue(prop->obj()); | 2410 VisitForAccumulatorValue(prop->obj()); |
| 2410 __ mov(r1, r0); | 2411 __ mov(r1, r0); |
| 2411 __ pop(r0); // Restore value. | 2412 __ pop(r0); // Restore value. |
| 2412 __ mov(r2, Operand(prop->key()->AsLiteral()->value())); | 2413 __ mov(r2, Operand(prop->key()->AsLiteral()->value())); |
| 2413 Handle<Code> ic = is_classic_mode() | 2414 CallStoreIC(NOT_CONTEXTUAL); |
| 2414 ? isolate()->builtins()->StoreIC_Initialize() | |
| 2415 : isolate()->builtins()->StoreIC_Initialize_Strict(); | |
| 2416 CallIC(ic); | |
| 2417 break; | 2415 break; |
| 2418 } | 2416 } |
| 2419 case KEYED_PROPERTY: { | 2417 case KEYED_PROPERTY: { |
| 2420 __ push(r0); // Preserve value. | 2418 __ push(r0); // Preserve value. |
| 2421 VisitForStackValue(prop->obj()); | 2419 VisitForStackValue(prop->obj()); |
| 2422 VisitForAccumulatorValue(prop->key()); | 2420 VisitForAccumulatorValue(prop->key()); |
| 2423 __ mov(r1, r0); | 2421 __ mov(r1, r0); |
| 2424 __ Pop(r0, r2); // r0 = restored value. | 2422 __ Pop(r0, r2); // r0 = restored value. |
| 2425 Handle<Code> ic = is_classic_mode() | 2423 Handle<Code> ic = is_classic_mode() |
| 2426 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2424 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2427 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2425 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2428 CallIC(ic); | 2426 CallIC(ic); |
| 2429 break; | 2427 break; |
| 2430 } | 2428 } |
| 2431 } | 2429 } |
| 2432 context()->Plug(r0); | 2430 context()->Plug(r0); |
| 2433 } | 2431 } |
| 2434 | 2432 |
| 2435 | 2433 |
| 2436 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 2434 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
| 2437 Token::Value op) { | 2435 Token::Value op) { |
| 2438 if (var->IsUnallocated()) { | 2436 if (var->IsUnallocated()) { |
| 2439 // Global var, const, or let. | 2437 // Global var, const, or let. |
| 2440 __ mov(r2, Operand(var->name())); | 2438 __ mov(r2, Operand(var->name())); |
| 2441 __ ldr(r1, GlobalObjectOperand()); | 2439 __ ldr(r1, GlobalObjectOperand()); |
| 2442 Handle<Code> ic = is_classic_mode() | 2440 CallStoreIC(CONTEXTUAL); |
| 2443 ? isolate()->builtins()->StoreIC_Initialize() | |
| 2444 : isolate()->builtins()->StoreIC_Initialize_Strict(); | |
| 2445 CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); | |
| 2446 | |
| 2447 } else if (op == Token::INIT_CONST) { | 2441 } else if (op == Token::INIT_CONST) { |
| 2448 // Const initializers need a write barrier. | 2442 // Const initializers need a write barrier. |
| 2449 ASSERT(!var->IsParameter()); // No const parameters. | 2443 ASSERT(!var->IsParameter()); // No const parameters. |
| 2450 if (var->IsStackLocal()) { | 2444 if (var->IsStackLocal()) { |
| 2451 __ ldr(r1, StackOperand(var)); | 2445 __ ldr(r1, StackOperand(var)); |
| 2452 __ CompareRoot(r1, Heap::kTheHoleValueRootIndex); | 2446 __ CompareRoot(r1, Heap::kTheHoleValueRootIndex); |
| 2453 __ str(result_register(), StackOperand(var), eq); | 2447 __ str(result_register(), StackOperand(var), eq); |
| 2454 } else { | 2448 } else { |
| 2455 ASSERT(var->IsContextSlot() || var->IsLookupSlot()); | 2449 ASSERT(var->IsContextSlot() || var->IsLookupSlot()); |
| 2456 // Like var declarations, const declarations are hoisted to function | 2450 // Like var declarations, const declarations are hoisted to function |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2530 // Assignment to a property, using a named store IC. | 2524 // Assignment to a property, using a named store IC. |
| 2531 Property* prop = expr->target()->AsProperty(); | 2525 Property* prop = expr->target()->AsProperty(); |
| 2532 ASSERT(prop != NULL); | 2526 ASSERT(prop != NULL); |
| 2533 ASSERT(prop->key()->AsLiteral() != NULL); | 2527 ASSERT(prop->key()->AsLiteral() != NULL); |
| 2534 | 2528 |
| 2535 // Record source code position before IC call. | 2529 // Record source code position before IC call. |
| 2536 SetSourcePosition(expr->position()); | 2530 SetSourcePosition(expr->position()); |
| 2537 __ mov(r2, Operand(prop->key()->AsLiteral()->value())); | 2531 __ mov(r2, Operand(prop->key()->AsLiteral()->value())); |
| 2538 __ pop(r1); | 2532 __ pop(r1); |
| 2539 | 2533 |
| 2540 Handle<Code> ic = is_classic_mode() | 2534 CallStoreIC(NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); |
| 2541 ? isolate()->builtins()->StoreIC_Initialize() | |
| 2542 : isolate()->builtins()->StoreIC_Initialize_Strict(); | |
| 2543 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); | |
| 2544 | 2535 |
| 2545 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2536 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2546 context()->Plug(r0); | 2537 context()->Plug(r0); |
| 2547 } | 2538 } |
| 2548 | 2539 |
| 2549 | 2540 |
| 2550 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2541 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 2551 // Assignment to a property, using a keyed store IC. | 2542 // Assignment to a property, using a keyed store IC. |
| 2552 | 2543 |
| 2553 // Record source code position before IC call. | 2544 // Record source code position before IC call. |
| 2554 SetSourcePosition(expr->position()); | 2545 SetSourcePosition(expr->position()); |
| 2555 __ Pop(r2, r1); // r1 = key. | 2546 __ Pop(r2, r1); // r1 = key. |
| 2556 | 2547 |
| 2557 Handle<Code> ic = is_classic_mode() | 2548 Handle<Code> ic = is_classic_mode() |
| 2558 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2549 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2559 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2550 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2560 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); | 2551 CallIC(ic, NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); |
| 2561 | 2552 |
| 2562 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2553 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2563 context()->Plug(r0); | 2554 context()->Plug(r0); |
| 2564 } | 2555 } |
| 2565 | 2556 |
| 2566 | 2557 |
| 2567 void FullCodeGenerator::VisitProperty(Property* expr) { | 2558 void FullCodeGenerator::VisitProperty(Property* expr) { |
| 2568 Comment cmnt(masm_, "[ Property"); | 2559 Comment cmnt(masm_, "[ Property"); |
| 2569 Expression* key = expr->key(); | 2560 Expression* key = expr->key(); |
| 2570 | 2561 |
| 2571 if (key->IsPropertyName()) { | 2562 if (key->IsPropertyName()) { |
| 2572 VisitForAccumulatorValue(expr->obj()); | 2563 VisitForAccumulatorValue(expr->obj()); |
| 2573 EmitNamedPropertyLoad(expr); | 2564 EmitNamedPropertyLoad(expr); |
| 2574 PrepareForBailoutForId(expr->LoadId(), TOS_REG); | 2565 PrepareForBailoutForId(expr->LoadId(), TOS_REG); |
| 2575 context()->Plug(r0); | 2566 context()->Plug(r0); |
| 2576 } else { | 2567 } else { |
| 2577 VisitForStackValue(expr->obj()); | 2568 VisitForStackValue(expr->obj()); |
| 2578 VisitForAccumulatorValue(expr->key()); | 2569 VisitForAccumulatorValue(expr->key()); |
| 2579 __ pop(r1); | 2570 __ pop(r1); |
| 2580 EmitKeyedPropertyLoad(expr); | 2571 EmitKeyedPropertyLoad(expr); |
| 2581 context()->Plug(r0); | 2572 context()->Plug(r0); |
| 2582 } | 2573 } |
| 2583 } | 2574 } |
| 2584 | 2575 |
| 2585 | 2576 |
| 2586 void FullCodeGenerator::CallIC(Handle<Code> code, | 2577 void FullCodeGenerator::CallIC(Handle<Code> code, |
| 2587 RelocInfo::Mode rmode, | 2578 ContextualMode mode, |
| 2588 TypeFeedbackId ast_id) { | 2579 TypeFeedbackId ast_id) { |
| 2589 ic_total_count_++; | 2580 ic_total_count_++; |
| 2590 // All calls must have a predictable size in full-codegen code to ensure that | 2581 // All calls must have a predictable size in full-codegen code to ensure that |
| 2591 // the debugger can patch them correctly. | 2582 // the debugger can patch them correctly. |
| 2592 __ Call(code, rmode, ast_id, al, NEVER_INLINE_TARGET_ADDRESS); | 2583 ASSERT(mode != CONTEXTUAL || ast_id.IsNone()); |
| 2584 __ Call(code, RelocInfo::CODE_TARGET, ast_id, al, |
| 2585 NEVER_INLINE_TARGET_ADDRESS); |
| 2593 } | 2586 } |
| 2594 | 2587 |
| 2595 void FullCodeGenerator::EmitCallWithIC(Call* expr, | 2588 void FullCodeGenerator::EmitCallWithIC(Call* expr, |
| 2596 Handle<Object> name, | 2589 Handle<Object> name, |
| 2597 RelocInfo::Mode mode) { | 2590 ContextualMode mode) { |
| 2598 // Code common for calls using the IC. | 2591 // Code common for calls using the IC. |
| 2599 ZoneList<Expression*>* args = expr->arguments(); | 2592 ZoneList<Expression*>* args = expr->arguments(); |
| 2600 int arg_count = args->length(); | 2593 int arg_count = args->length(); |
| 2601 { PreservePositionScope scope(masm()->positions_recorder()); | 2594 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2602 for (int i = 0; i < arg_count; i++) { | 2595 for (int i = 0; i < arg_count; i++) { |
| 2603 VisitForStackValue(args->at(i)); | 2596 VisitForStackValue(args->at(i)); |
| 2604 } | 2597 } |
| 2605 __ mov(r2, Operand(name)); | 2598 __ mov(r2, Operand(name)); |
| 2606 } | 2599 } |
| 2607 // Record source position for debugger. | 2600 // Record source position for debugger. |
| 2608 SetSourcePosition(expr->position()); | 2601 SetSourcePosition(expr->position()); |
| 2609 // Call the IC initialization code. | 2602 // Call the IC initialization code. |
| 2610 Handle<Code> ic = | 2603 Handle<Code> ic = |
| 2611 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); | 2604 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); |
| 2612 CallIC(ic, mode, expr->CallFeedbackId()); | 2605 TypeFeedbackId ast_id = mode == CONTEXTUAL |
| 2606 ? TypeFeedbackId::None() |
| 2607 : expr->CallFeedbackId(); |
| 2608 CallIC(ic, mode, ast_id); |
| 2613 RecordJSReturnSite(expr); | 2609 RecordJSReturnSite(expr); |
| 2614 // Restore context register. | 2610 // Restore context register. |
| 2615 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2611 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2616 context()->Plug(r0); | 2612 context()->Plug(r0); |
| 2617 } | 2613 } |
| 2618 | 2614 |
| 2619 | 2615 |
| 2620 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2616 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
| 2621 Expression* key) { | 2617 Expression* key) { |
| 2622 // Load the key. | 2618 // Load the key. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2635 for (int i = 0; i < arg_count; i++) { | 2631 for (int i = 0; i < arg_count; i++) { |
| 2636 VisitForStackValue(args->at(i)); | 2632 VisitForStackValue(args->at(i)); |
| 2637 } | 2633 } |
| 2638 } | 2634 } |
| 2639 // Record source position for debugger. | 2635 // Record source position for debugger. |
| 2640 SetSourcePosition(expr->position()); | 2636 SetSourcePosition(expr->position()); |
| 2641 // Call the IC initialization code. | 2637 // Call the IC initialization code. |
| 2642 Handle<Code> ic = | 2638 Handle<Code> ic = |
| 2643 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); | 2639 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); |
| 2644 __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. | 2640 __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. |
| 2645 CallIC(ic, RelocInfo::CODE_TARGET, expr->CallFeedbackId()); | 2641 CallIC(ic, NOT_CONTEXTUAL, expr->CallFeedbackId()); |
| 2646 RecordJSReturnSite(expr); | 2642 RecordJSReturnSite(expr); |
| 2647 // Restore context register. | 2643 // Restore context register. |
| 2648 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2644 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2649 context()->DropAndPlug(1, r0); // Drop the key still on the stack. | 2645 context()->DropAndPlug(1, r0); // Drop the key still on the stack. |
| 2650 } | 2646 } |
| 2651 | 2647 |
| 2652 | 2648 |
| 2653 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { | 2649 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { |
| 2654 // Code common for calls using the call stub. | 2650 // Code common for calls using the call stub. |
| 2655 ZoneList<Expression*>* args = expr->arguments(); | 2651 ZoneList<Expression*>* args = expr->arguments(); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2741 EmitResolvePossiblyDirectEval(arg_count); | 2737 EmitResolvePossiblyDirectEval(arg_count); |
| 2742 | 2738 |
| 2743 // The runtime call returns a pair of values in r0 (function) and | 2739 // The runtime call returns a pair of values in r0 (function) and |
| 2744 // r1 (receiver). Touch up the stack with the right values. | 2740 // r1 (receiver). Touch up the stack with the right values. |
| 2745 __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 2741 __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
| 2746 __ str(r1, MemOperand(sp, arg_count * kPointerSize)); | 2742 __ str(r1, MemOperand(sp, arg_count * kPointerSize)); |
| 2747 } | 2743 } |
| 2748 | 2744 |
| 2749 // Record source position for debugger. | 2745 // Record source position for debugger. |
| 2750 SetSourcePosition(expr->position()); | 2746 SetSourcePosition(expr->position()); |
| 2751 CallFunctionStub stub(arg_count, RECEIVER_MIGHT_BE_IMPLICIT); | 2747 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS); |
| 2752 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 2748 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
| 2753 __ CallStub(&stub); | 2749 __ CallStub(&stub); |
| 2754 RecordJSReturnSite(expr); | 2750 RecordJSReturnSite(expr); |
| 2755 // Restore context register. | 2751 // Restore context register. |
| 2756 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2752 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2757 context()->DropAndPlug(1, r0); | 2753 context()->DropAndPlug(1, r0); |
| 2758 } else if (proxy != NULL && proxy->var()->IsUnallocated()) { | 2754 } else if (proxy != NULL && proxy->var()->IsUnallocated()) { |
| 2759 // Push global object as receiver for the call IC. | 2755 // Push global object as receiver for the call IC. |
| 2760 __ ldr(r0, GlobalObjectOperand()); | 2756 __ ldr(r0, GlobalObjectOperand()); |
| 2761 __ push(r0); | 2757 __ push(r0); |
| 2762 EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT); | 2758 EmitCallWithIC(expr, proxy->name(), CONTEXTUAL); |
| 2763 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { | 2759 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { |
| 2764 // Call to a lookup slot (dynamically introduced variable). | 2760 // Call to a lookup slot (dynamically introduced variable). |
| 2765 Label slow, done; | 2761 Label slow, done; |
| 2766 | 2762 |
| 2767 { PreservePositionScope scope(masm()->positions_recorder()); | 2763 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2768 // Generate code for loading from variables potentially shadowed | 2764 // Generate code for loading from variables potentially shadowed |
| 2769 // by eval-introduced variables. | 2765 // by eval-introduced variables. |
| 2770 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); | 2766 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); |
| 2771 } | 2767 } |
| 2772 | 2768 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2783 // function and receiver and have the slow path jump around this | 2779 // function and receiver and have the slow path jump around this |
| 2784 // code. | 2780 // code. |
| 2785 if (done.is_linked()) { | 2781 if (done.is_linked()) { |
| 2786 Label call; | 2782 Label call; |
| 2787 __ b(&call); | 2783 __ b(&call); |
| 2788 __ bind(&done); | 2784 __ bind(&done); |
| 2789 // Push function. | 2785 // Push function. |
| 2790 __ push(r0); | 2786 __ push(r0); |
| 2791 // The receiver is implicitly the global receiver. Indicate this | 2787 // The receiver is implicitly the global receiver. Indicate this |
| 2792 // by passing the hole to the call function stub. | 2788 // by passing the hole to the call function stub. |
| 2793 __ LoadRoot(r1, Heap::kTheHoleValueRootIndex); | 2789 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); |
| 2794 __ push(r1); | 2790 __ push(r1); |
| 2795 __ bind(&call); | 2791 __ bind(&call); |
| 2796 } | 2792 } |
| 2797 | 2793 |
| 2798 // The receiver is either the global receiver or an object found | 2794 // The receiver is either the global receiver or an object found |
| 2799 // by LoadContextSlot. That object could be the hole if the | 2795 // by LoadContextSlot. |
| 2800 // receiver is implicitly the global object. | 2796 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); |
| 2801 EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT); | |
| 2802 } else if (property != NULL) { | 2797 } else if (property != NULL) { |
| 2803 { PreservePositionScope scope(masm()->positions_recorder()); | 2798 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2804 VisitForStackValue(property->obj()); | 2799 VisitForStackValue(property->obj()); |
| 2805 } | 2800 } |
| 2806 if (property->key()->IsPropertyName()) { | 2801 if (property->key()->IsPropertyName()) { |
| 2807 EmitCallWithIC(expr, | 2802 EmitCallWithIC(expr, |
| 2808 property->key()->AsLiteral()->value(), | 2803 property->key()->AsLiteral()->value(), |
| 2809 RelocInfo::CODE_TARGET); | 2804 NOT_CONTEXTUAL); |
| 2810 } else { | 2805 } else { |
| 2811 EmitKeyedCallWithIC(expr, property->key()); | 2806 EmitKeyedCallWithIC(expr, property->key()); |
| 2812 } | 2807 } |
| 2813 } else { | 2808 } else { |
| 2814 // Call to an arbitrary expression not handled specially above. | 2809 // Call to an arbitrary expression not handled specially above. |
| 2815 { PreservePositionScope scope(masm()->positions_recorder()); | 2810 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2816 VisitForStackValue(callee); | 2811 VisitForStackValue(callee); |
| 2817 } | 2812 } |
| 2818 // Load global receiver object. | 2813 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); |
| 2819 __ ldr(r1, GlobalObjectOperand()); | |
| 2820 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); | |
| 2821 __ push(r1); | 2814 __ push(r1); |
| 2822 // Emit function call. | 2815 // Emit function call. |
| 2823 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); | 2816 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); |
| 2824 } | 2817 } |
| 2825 | 2818 |
| 2826 #ifdef DEBUG | 2819 #ifdef DEBUG |
| 2827 // RecordJSReturnSite should have been called. | 2820 // RecordJSReturnSite should have been called. |
| 2828 ASSERT(expr->return_is_recorded_); | 2821 ASSERT(expr->return_is_recorded_); |
| 2829 #endif | 2822 #endif |
| 2830 } | 2823 } |
| (...skipping 899 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3730 Label runtime, done; | 3723 Label runtime, done; |
| 3731 // Check for non-function argument (including proxy). | 3724 // Check for non-function argument (including proxy). |
| 3732 __ JumpIfSmi(r0, &runtime); | 3725 __ JumpIfSmi(r0, &runtime); |
| 3733 __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE); | 3726 __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE); |
| 3734 __ b(ne, &runtime); | 3727 __ b(ne, &runtime); |
| 3735 | 3728 |
| 3736 // InvokeFunction requires the function in r1. Move it in there. | 3729 // InvokeFunction requires the function in r1. Move it in there. |
| 3737 __ mov(r1, result_register()); | 3730 __ mov(r1, result_register()); |
| 3738 ParameterCount count(arg_count); | 3731 ParameterCount count(arg_count); |
| 3739 __ InvokeFunction(r1, count, CALL_FUNCTION, | 3732 __ InvokeFunction(r1, count, CALL_FUNCTION, |
| 3740 NullCallWrapper(), CALL_AS_METHOD); | 3733 NullCallWrapper(), CALL_AS_FUNCTION); |
| 3741 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3734 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 3742 __ jmp(&done); | 3735 __ jmp(&done); |
| 3743 | 3736 |
| 3744 __ bind(&runtime); | 3737 __ bind(&runtime); |
| 3745 __ push(r0); | 3738 __ push(r0); |
| 3746 __ CallRuntime(Runtime::kCall, args->length()); | 3739 __ CallRuntime(Runtime::kCall, args->length()); |
| 3747 __ bind(&done); | 3740 __ bind(&done); |
| 3748 | 3741 |
| 3749 context()->Plug(r0); | 3742 context()->Plug(r0); |
| 3750 } | 3743 } |
| (...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4142 | 4135 |
| 4143 // Push the arguments ("left-to-right"). | 4136 // Push the arguments ("left-to-right"). |
| 4144 int arg_count = args->length(); | 4137 int arg_count = args->length(); |
| 4145 for (int i = 0; i < arg_count; i++) { | 4138 for (int i = 0; i < arg_count; i++) { |
| 4146 VisitForStackValue(args->at(i)); | 4139 VisitForStackValue(args->at(i)); |
| 4147 } | 4140 } |
| 4148 | 4141 |
| 4149 if (expr->is_jsruntime()) { | 4142 if (expr->is_jsruntime()) { |
| 4150 // Call the JS runtime function. | 4143 // Call the JS runtime function. |
| 4151 __ mov(r2, Operand(expr->name())); | 4144 __ mov(r2, Operand(expr->name())); |
| 4152 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; | 4145 ContextualMode mode = NOT_CONTEXTUAL; |
| 4153 Handle<Code> ic = | 4146 Handle<Code> ic = |
| 4154 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); | 4147 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); |
| 4155 CallIC(ic, mode, expr->CallRuntimeFeedbackId()); | 4148 CallIC(ic, mode, expr->CallRuntimeFeedbackId()); |
| 4156 // Restore context register. | 4149 // Restore context register. |
| 4157 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4150 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 4158 } else { | 4151 } else { |
| 4159 // Call the C runtime function. | 4152 // Call the C runtime function. |
| 4160 __ CallRuntime(expr->function(), arg_count); | 4153 __ CallRuntime(expr->function(), arg_count); |
| 4161 } | 4154 } |
| 4162 context()->Plug(r0); | 4155 context()->Plug(r0); |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4393 | 4386 |
| 4394 __ bind(&stub_call); | 4387 __ bind(&stub_call); |
| 4395 __ mov(r1, r0); | 4388 __ mov(r1, r0); |
| 4396 __ mov(r0, Operand(Smi::FromInt(count_value))); | 4389 __ mov(r0, Operand(Smi::FromInt(count_value))); |
| 4397 | 4390 |
| 4398 // Record position before stub call. | 4391 // Record position before stub call. |
| 4399 SetSourcePosition(expr->position()); | 4392 SetSourcePosition(expr->position()); |
| 4400 | 4393 |
| 4401 BinaryOpICStub stub(Token::ADD, NO_OVERWRITE); | 4394 BinaryOpICStub stub(Token::ADD, NO_OVERWRITE); |
| 4402 CallIC(stub.GetCode(isolate()), | 4395 CallIC(stub.GetCode(isolate()), |
| 4403 RelocInfo::CODE_TARGET, | 4396 NOT_CONTEXTUAL, |
| 4404 expr->CountBinOpFeedbackId()); | 4397 expr->CountBinOpFeedbackId()); |
| 4405 patch_site.EmitPatchInfo(); | 4398 patch_site.EmitPatchInfo(); |
| 4406 __ bind(&done); | 4399 __ bind(&done); |
| 4407 | 4400 |
| 4408 // Store the value returned in r0. | 4401 // Store the value returned in r0. |
| 4409 switch (assign_type) { | 4402 switch (assign_type) { |
| 4410 case VARIABLE: | 4403 case VARIABLE: |
| 4411 if (expr->is_postfix()) { | 4404 if (expr->is_postfix()) { |
| 4412 { EffectContext context(this); | 4405 { EffectContext context(this); |
| 4413 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 4406 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 4414 Token::ASSIGN); | 4407 Token::ASSIGN); |
| 4415 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4408 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4416 context.Plug(r0); | 4409 context.Plug(r0); |
| 4417 } | 4410 } |
| 4418 // For all contexts except EffectConstant We have the result on | 4411 // For all contexts except EffectConstant We have the result on |
| 4419 // top of the stack. | 4412 // top of the stack. |
| 4420 if (!context()->IsEffect()) { | 4413 if (!context()->IsEffect()) { |
| 4421 context()->PlugTOS(); | 4414 context()->PlugTOS(); |
| 4422 } | 4415 } |
| 4423 } else { | 4416 } else { |
| 4424 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 4417 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 4425 Token::ASSIGN); | 4418 Token::ASSIGN); |
| 4426 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4419 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4427 context()->Plug(r0); | 4420 context()->Plug(r0); |
| 4428 } | 4421 } |
| 4429 break; | 4422 break; |
| 4430 case NAMED_PROPERTY: { | 4423 case NAMED_PROPERTY: { |
| 4431 __ mov(r2, Operand(prop->key()->AsLiteral()->value())); | 4424 __ mov(r2, Operand(prop->key()->AsLiteral()->value())); |
| 4432 __ pop(r1); | 4425 __ pop(r1); |
| 4433 Handle<Code> ic = is_classic_mode() | 4426 CallStoreIC(NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); |
| 4434 ? isolate()->builtins()->StoreIC_Initialize() | |
| 4435 : isolate()->builtins()->StoreIC_Initialize_Strict(); | |
| 4436 CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); | |
| 4437 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4427 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4438 if (expr->is_postfix()) { | 4428 if (expr->is_postfix()) { |
| 4439 if (!context()->IsEffect()) { | 4429 if (!context()->IsEffect()) { |
| 4440 context()->PlugTOS(); | 4430 context()->PlugTOS(); |
| 4441 } | 4431 } |
| 4442 } else { | 4432 } else { |
| 4443 context()->Plug(r0); | 4433 context()->Plug(r0); |
| 4444 } | 4434 } |
| 4445 break; | 4435 break; |
| 4446 } | 4436 } |
| 4447 case KEYED_PROPERTY: { | 4437 case KEYED_PROPERTY: { |
| 4448 __ Pop(r2, r1); // r1 = key. r2 = receiver. | 4438 __ Pop(r2, r1); // r1 = key. r2 = receiver. |
| 4449 Handle<Code> ic = is_classic_mode() | 4439 Handle<Code> ic = is_classic_mode() |
| 4450 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 4440 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 4451 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 4441 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 4452 CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); | 4442 CallIC(ic, NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); |
| 4453 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4443 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4454 if (expr->is_postfix()) { | 4444 if (expr->is_postfix()) { |
| 4455 if (!context()->IsEffect()) { | 4445 if (!context()->IsEffect()) { |
| 4456 context()->PlugTOS(); | 4446 context()->PlugTOS(); |
| 4457 } | 4447 } |
| 4458 } else { | 4448 } else { |
| 4459 context()->Plug(r0); | 4449 context()->Plug(r0); |
| 4460 } | 4450 } |
| 4461 break; | 4451 break; |
| 4462 } | 4452 } |
| 4463 } | 4453 } |
| 4464 } | 4454 } |
| 4465 | 4455 |
| 4466 | 4456 |
| 4467 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | 4457 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { |
| 4468 ASSERT(!context()->IsEffect()); | 4458 ASSERT(!context()->IsEffect()); |
| 4469 ASSERT(!context()->IsTest()); | 4459 ASSERT(!context()->IsTest()); |
| 4470 VariableProxy* proxy = expr->AsVariableProxy(); | 4460 VariableProxy* proxy = expr->AsVariableProxy(); |
| 4471 if (proxy != NULL && proxy->var()->IsUnallocated()) { | 4461 if (proxy != NULL && proxy->var()->IsUnallocated()) { |
| 4472 Comment cmnt(masm_, "Global variable"); | 4462 Comment cmnt(masm_, "Global variable"); |
| 4473 __ ldr(r0, GlobalObjectOperand()); | 4463 __ ldr(r0, GlobalObjectOperand()); |
| 4474 __ mov(r2, Operand(proxy->name())); | 4464 __ mov(r2, Operand(proxy->name())); |
| 4475 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | |
| 4476 // Use a regular load, not a contextual load, to avoid a reference | 4465 // Use a regular load, not a contextual load, to avoid a reference |
| 4477 // error. | 4466 // error. |
| 4478 CallIC(ic); | 4467 CallLoadIC(NOT_CONTEXTUAL); |
| 4479 PrepareForBailout(expr, TOS_REG); | 4468 PrepareForBailout(expr, TOS_REG); |
| 4480 context()->Plug(r0); | 4469 context()->Plug(r0); |
| 4481 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { | 4470 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { |
| 4482 Label done, slow; | 4471 Label done, slow; |
| 4483 | 4472 |
| 4484 // Generate code for loading from variables potentially shadowed | 4473 // Generate code for loading from variables potentially shadowed |
| 4485 // by eval-introduced variables. | 4474 // by eval-introduced variables. |
| 4486 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); | 4475 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); |
| 4487 | 4476 |
| 4488 __ bind(&slow); | 4477 __ bind(&slow); |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4633 __ orr(r2, r0, Operand(r1)); | 4622 __ orr(r2, r0, Operand(r1)); |
| 4634 patch_site.EmitJumpIfNotSmi(r2, &slow_case); | 4623 patch_site.EmitJumpIfNotSmi(r2, &slow_case); |
| 4635 __ cmp(r1, r0); | 4624 __ cmp(r1, r0); |
| 4636 Split(cond, if_true, if_false, NULL); | 4625 Split(cond, if_true, if_false, NULL); |
| 4637 __ bind(&slow_case); | 4626 __ bind(&slow_case); |
| 4638 } | 4627 } |
| 4639 | 4628 |
| 4640 // Record position and call the compare IC. | 4629 // Record position and call the compare IC. |
| 4641 SetSourcePosition(expr->position()); | 4630 SetSourcePosition(expr->position()); |
| 4642 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 4631 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
| 4643 CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); | 4632 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); |
| 4644 patch_site.EmitPatchInfo(); | 4633 patch_site.EmitPatchInfo(); |
| 4645 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 4634 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 4646 __ cmp(r0, Operand::Zero()); | 4635 __ cmp(r0, Operand::Zero()); |
| 4647 Split(cond, if_true, if_false, fall_through); | 4636 Split(cond, if_true, if_false, fall_through); |
| 4648 } | 4637 } |
| 4649 } | 4638 } |
| 4650 | 4639 |
| 4651 // Convert the result of the comparison into one expected for this | 4640 // Convert the result of the comparison into one expected for this |
| 4652 // expression's context. | 4641 // expression's context. |
| 4653 context()->Plug(if_true, if_false); | 4642 context()->Plug(if_true, if_false); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4668 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 4657 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 4669 if (expr->op() == Token::EQ_STRICT) { | 4658 if (expr->op() == Token::EQ_STRICT) { |
| 4670 Heap::RootListIndex nil_value = nil == kNullValue ? | 4659 Heap::RootListIndex nil_value = nil == kNullValue ? |
| 4671 Heap::kNullValueRootIndex : | 4660 Heap::kNullValueRootIndex : |
| 4672 Heap::kUndefinedValueRootIndex; | 4661 Heap::kUndefinedValueRootIndex; |
| 4673 __ LoadRoot(r1, nil_value); | 4662 __ LoadRoot(r1, nil_value); |
| 4674 __ cmp(r0, r1); | 4663 __ cmp(r0, r1); |
| 4675 Split(eq, if_true, if_false, fall_through); | 4664 Split(eq, if_true, if_false, fall_through); |
| 4676 } else { | 4665 } else { |
| 4677 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); | 4666 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); |
| 4678 CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); | 4667 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); |
| 4679 __ cmp(r0, Operand(0)); | 4668 __ cmp(r0, Operand(0)); |
| 4680 Split(ne, if_true, if_false, fall_through); | 4669 Split(ne, if_true, if_false, fall_through); |
| 4681 } | 4670 } |
| 4682 context()->Plug(if_true, if_false); | 4671 context()->Plug(if_true, if_false); |
| 4683 } | 4672 } |
| 4684 | 4673 |
| 4685 | 4674 |
| 4686 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 4675 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
| 4687 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 4676 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 4688 context()->Plug(r0); | 4677 context()->Plug(r0); |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4911 ASSERT(Memory::uint32_at(interrupt_address_pointer) == | 4900 ASSERT(Memory::uint32_at(interrupt_address_pointer) == |
| 4912 reinterpret_cast<uint32_t>( | 4901 reinterpret_cast<uint32_t>( |
| 4913 isolate->builtins()->OsrAfterStackCheck()->entry())); | 4902 isolate->builtins()->OsrAfterStackCheck()->entry())); |
| 4914 return OSR_AFTER_STACK_CHECK; | 4903 return OSR_AFTER_STACK_CHECK; |
| 4915 } | 4904 } |
| 4916 | 4905 |
| 4917 | 4906 |
| 4918 } } // namespace v8::internal | 4907 } } // namespace v8::internal |
| 4919 | 4908 |
| 4920 #endif // V8_TARGET_ARCH_ARM | 4909 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |