| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 | 136 |
| 137 ProfileEntryHookStub::MaybeCallEntryHook(masm_); | 137 ProfileEntryHookStub::MaybeCallEntryHook(masm_); |
| 138 | 138 |
| 139 #ifdef DEBUG | 139 #ifdef DEBUG |
| 140 if (strlen(FLAG_stop_at) > 0 && | 140 if (strlen(FLAG_stop_at) > 0 && |
| 141 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { | 141 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { |
| 142 __ Debug("stop-at", __LINE__, BREAK); | 142 __ Debug("stop-at", __LINE__, BREAK); |
| 143 } | 143 } |
| 144 #endif | 144 #endif |
| 145 | 145 |
| 146 // Strict mode functions and builtins need to replace the receiver | 146 // Classic mode functions and builtins need to replace the receiver with the |
| 147 // with undefined when called as functions (without an explicit | 147 // global proxy when called as functions (without an explicit receiver |
| 148 // receiver object). x5 is zero for method calls and non-zero for | 148 // object). |
| 149 // function calls. | 149 if (info->is_classic_mode() && !info->is_native()) { |
| 150 if (!info->is_classic_mode() || info->is_native()) { | |
| 151 Label ok; | 150 Label ok; |
| 152 __ Cbz(x5, &ok); | 151 __ Cbz(x5, &ok); |
| 153 int receiver_offset = info->scope()->num_parameters() * kXRegSizeInBytes; | 152 int receiver_offset = info->scope()->num_parameters() * kXRegSizeInBytes; |
| 154 __ LoadRoot(x10, Heap::kUndefinedValueRootIndex); | 153 __ Peek(x10, receiver_offset); |
| 154 __ JumpIfNotRoot(x10, Heap::kUndefinedValueRootIndex, &ok); |
| 155 |
| 156 __ Ldr(x10, GlobalObjectMemOperand()); |
| 157 __ Ldr(x10, FieldMemOperand(x10, GlobalObject::kGlobalReceiverOffset)); |
| 155 __ Poke(x10, receiver_offset); | 158 __ Poke(x10, receiver_offset); |
| 159 |
| 156 __ Bind(&ok); | 160 __ Bind(&ok); |
| 157 } | 161 } |
| 158 | 162 |
| 159 | 163 |
| 160 // Open a frame scope to indicate that there is a frame on the stack. | 164 // Open a frame scope to indicate that there is a frame on the stack. |
| 161 // The MANUAL indicates that the scope shouldn't actually generate code | 165 // The MANUAL indicates that the scope shouldn't actually generate code |
| 162 // to set up the frame because we do it manually below. | 166 // to set up the frame because we do it manually below. |
| 163 FrameScope frame_scope(masm_, StackFrame::MANUAL); | 167 FrameScope frame_scope(masm_, StackFrame::MANUAL); |
| 164 | 168 |
| 165 // This call emits the following sequence in a way that can be patched for | 169 // This call emits the following sequence in a way that can be patched for |
| (...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 653 } | 657 } |
| 654 } | 658 } |
| 655 } | 659 } |
| 656 | 660 |
| 657 | 661 |
| 658 void FullCodeGenerator::DoTest(Expression* condition, | 662 void FullCodeGenerator::DoTest(Expression* condition, |
| 659 Label* if_true, | 663 Label* if_true, |
| 660 Label* if_false, | 664 Label* if_false, |
| 661 Label* fall_through) { | 665 Label* fall_through) { |
| 662 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); | 666 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); |
| 663 CallIC(ic, RelocInfo::CODE_TARGET, condition->test_id()); | 667 CallIC(ic, NOT_CONTEXTUAL, condition->test_id()); |
| 664 __ CompareAndSplit(result_register(), 0, ne, if_true, if_false, fall_through); | 668 __ CompareAndSplit(result_register(), 0, ne, if_true, if_false, fall_through); |
| 665 } | 669 } |
| 666 | 670 |
| 667 | 671 |
| 668 // If (cond), branch to if_true. | 672 // If (cond), branch to if_true. |
| 669 // If (!cond), branch to if_false. | 673 // If (!cond), branch to if_false. |
| 670 // fall_through is used as an optimization in cases where only one branch | 674 // fall_through is used as an optimization in cases where only one branch |
| 671 // instruction is necessary. | 675 // instruction is necessary. |
| 672 void FullCodeGenerator::Split(Condition cond, | 676 void FullCodeGenerator::Split(Condition cond, |
| 673 Label* if_true, | 677 Label* if_true, |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1021 __ Cmp(x1, x0); | 1025 __ Cmp(x1, x0); |
| 1022 __ B(ne, &next_test); | 1026 __ B(ne, &next_test); |
| 1023 __ Drop(1); // Switch value is no longer needed. | 1027 __ Drop(1); // Switch value is no longer needed. |
| 1024 __ B(clause->body_target()); | 1028 __ B(clause->body_target()); |
| 1025 __ Bind(&slow_case); | 1029 __ Bind(&slow_case); |
| 1026 } | 1030 } |
| 1027 | 1031 |
| 1028 // Record position before stub call for type feedback. | 1032 // Record position before stub call for type feedback. |
| 1029 SetSourcePosition(clause->position()); | 1033 SetSourcePosition(clause->position()); |
| 1030 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); | 1034 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); |
| 1031 CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId()); | 1035 CallIC(ic, NOT_CONTEXTUAL, clause->CompareId()); |
| 1032 patch_site.EmitPatchInfo(); | 1036 patch_site.EmitPatchInfo(); |
| 1033 | 1037 |
| 1034 Label skip; | 1038 Label skip; |
| 1035 __ B(&skip); | 1039 __ B(&skip); |
| 1036 PrepareForBailout(clause, TOS_REG); | 1040 PrepareForBailout(clause, TOS_REG); |
| 1037 __ JumpIfNotRoot(x0, Heap::kTrueValueRootIndex, &next_test); | 1041 __ JumpIfNotRoot(x0, Heap::kTrueValueRootIndex, &next_test); |
| 1038 __ Drop(1); | 1042 __ Drop(1); |
| 1039 __ B(clause->body_target()); | 1043 __ B(clause->body_target()); |
| 1040 __ Bind(&skip); | 1044 __ Bind(&skip); |
| 1041 | 1045 |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1376 __ Ldr(temp, ContextMemOperand(next, Context::EXTENSION_INDEX)); | 1380 __ Ldr(temp, ContextMemOperand(next, Context::EXTENSION_INDEX)); |
| 1377 __ Cbnz(temp, slow); | 1381 __ Cbnz(temp, slow); |
| 1378 // Load next context in chain. | 1382 // Load next context in chain. |
| 1379 __ Ldr(next, ContextMemOperand(next, Context::PREVIOUS_INDEX)); | 1383 __ Ldr(next, ContextMemOperand(next, Context::PREVIOUS_INDEX)); |
| 1380 __ B(&loop); | 1384 __ B(&loop); |
| 1381 __ Bind(&fast); | 1385 __ Bind(&fast); |
| 1382 } | 1386 } |
| 1383 | 1387 |
| 1384 __ Ldr(x0, GlobalObjectMemOperand()); | 1388 __ Ldr(x0, GlobalObjectMemOperand()); |
| 1385 __ Mov(x2, Operand(var->name())); | 1389 __ Mov(x2, Operand(var->name())); |
| 1386 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) | 1390 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) ? NOT_CONTEXTUAL |
| 1387 ? RelocInfo::CODE_TARGET | 1391 : CONTEXTUAL; |
| 1388 : RelocInfo::CODE_TARGET_CONTEXT; | 1392 CallLoadIC(mode); |
| 1389 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | |
| 1390 CallIC(ic, mode); | |
| 1391 } | 1393 } |
| 1392 | 1394 |
| 1393 | 1395 |
| 1394 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1396 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
| 1395 Label* slow) { | 1397 Label* slow) { |
| 1396 ASSERT(var->IsContextSlot()); | 1398 ASSERT(var->IsContextSlot()); |
| 1397 Register context = cp; | 1399 Register context = cp; |
| 1398 Register next = x10; | 1400 Register next = x10; |
| 1399 Register temp = x11; | 1401 Register temp = x11; |
| 1400 | 1402 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1460 | 1462 |
| 1461 // Three cases: global variables, lookup variables, and all other types of | 1463 // Three cases: global variables, lookup variables, and all other types of |
| 1462 // variables. | 1464 // variables. |
| 1463 switch (var->location()) { | 1465 switch (var->location()) { |
| 1464 case Variable::UNALLOCATED: { | 1466 case Variable::UNALLOCATED: { |
| 1465 Comment cmnt(masm_, "Global variable"); | 1467 Comment cmnt(masm_, "Global variable"); |
| 1466 // Use inline caching. Variable name is passed in x2 and the global | 1468 // Use inline caching. Variable name is passed in x2 and the global |
| 1467 // object (receiver) in x0. | 1469 // object (receiver) in x0. |
| 1468 __ Ldr(x0, GlobalObjectMemOperand()); | 1470 __ Ldr(x0, GlobalObjectMemOperand()); |
| 1469 __ Mov(x2, Operand(var->name())); | 1471 __ Mov(x2, Operand(var->name())); |
| 1470 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1472 CallLoadIC(CONTEXTUAL); |
| 1471 CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); | |
| 1472 context()->Plug(x0); | 1473 context()->Plug(x0); |
| 1473 break; | 1474 break; |
| 1474 } | 1475 } |
| 1475 | 1476 |
| 1476 case Variable::PARAMETER: | 1477 case Variable::PARAMETER: |
| 1477 case Variable::LOCAL: | 1478 case Variable::LOCAL: |
| 1478 case Variable::CONTEXT: { | 1479 case Variable::CONTEXT: { |
| 1479 Comment cmnt(masm_, var->IsContextSlot() | 1480 Comment cmnt(masm_, var->IsContextSlot() |
| 1480 ? "Context variable" | 1481 ? "Context variable" |
| 1481 : "Stack variable"); | 1482 : "Stack variable"); |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1671 UNREACHABLE(); | 1672 UNREACHABLE(); |
| 1672 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1673 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1673 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); | 1674 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); |
| 1674 // Fall through. | 1675 // Fall through. |
| 1675 case ObjectLiteral::Property::COMPUTED: | 1676 case ObjectLiteral::Property::COMPUTED: |
| 1676 if (key->value()->IsInternalizedString()) { | 1677 if (key->value()->IsInternalizedString()) { |
| 1677 if (property->emit_store()) { | 1678 if (property->emit_store()) { |
| 1678 VisitForAccumulatorValue(value); | 1679 VisitForAccumulatorValue(value); |
| 1679 __ Mov(x2, Operand(key->value())); | 1680 __ Mov(x2, Operand(key->value())); |
| 1680 __ Peek(x1, 0); | 1681 __ Peek(x1, 0); |
| 1681 Handle<Code> ic = is_classic_mode() | 1682 CallStoreIC(NOT_CONTEXTUAL, key->LiteralFeedbackId()); |
| 1682 ? isolate()->builtins()->StoreIC_Initialize() | |
| 1683 : isolate()->builtins()->StoreIC_Initialize_Strict(); | |
| 1684 CallIC(ic, RelocInfo::CODE_TARGET, key->LiteralFeedbackId()); | |
| 1685 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1683 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
| 1686 } else { | 1684 } else { |
| 1687 VisitForEffect(value); | 1685 VisitForEffect(value); |
| 1688 } | 1686 } |
| 1689 break; | 1687 break; |
| 1690 } | 1688 } |
| 1691 // Duplicate receiver on stack. | 1689 // Duplicate receiver on stack. |
| 1692 __ Peek(x0, 0); | 1690 __ Peek(x0, 0); |
| 1693 __ Push(x0); | 1691 __ Push(x0); |
| 1694 VisitForStackValue(key); | 1692 VisitForStackValue(key); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1763 ZoneList<Expression*>* subexprs = expr->values(); | 1761 ZoneList<Expression*>* subexprs = expr->values(); |
| 1764 int length = subexprs->length(); | 1762 int length = subexprs->length(); |
| 1765 Handle<FixedArray> constant_elements = expr->constant_elements(); | 1763 Handle<FixedArray> constant_elements = expr->constant_elements(); |
| 1766 ASSERT_EQ(2, constant_elements->length()); | 1764 ASSERT_EQ(2, constant_elements->length()); |
| 1767 ElementsKind constant_elements_kind = | 1765 ElementsKind constant_elements_kind = |
| 1768 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); | 1766 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); |
| 1769 bool has_fast_elements = IsFastObjectElementsKind(constant_elements_kind); | 1767 bool has_fast_elements = IsFastObjectElementsKind(constant_elements_kind); |
| 1770 Handle<FixedArrayBase> constant_elements_values( | 1768 Handle<FixedArrayBase> constant_elements_values( |
| 1771 FixedArrayBase::cast(constant_elements->get(1))); | 1769 FixedArrayBase::cast(constant_elements->get(1))); |
| 1772 | 1770 |
| 1773 AllocationSiteMode allocation_site_mode = | 1771 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE; |
| 1774 FLAG_track_allocation_sites ? TRACK_ALLOCATION_SITE | |
| 1775 : DONT_TRACK_ALLOCATION_SITE; | |
| 1776 if (has_fast_elements && !FLAG_allocation_site_pretenuring) { | 1772 if (has_fast_elements && !FLAG_allocation_site_pretenuring) { |
| 1777 // If the only customer of allocation sites is transitioning, then | 1773 // If the only customer of allocation sites is transitioning, then |
| 1778 // we can turn it off if we don't have anywhere else to transition to. | 1774 // we can turn it off if we don't have anywhere else to transition to. |
| 1779 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; | 1775 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; |
| 1780 } | 1776 } |
| 1781 | 1777 |
| 1782 __ Ldr(x3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1778 __ Ldr(x3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1783 __ Ldr(x3, FieldMemOperand(x3, JSFunction::kLiteralsOffset)); | 1779 __ Ldr(x3, FieldMemOperand(x3, JSFunction::kLiteralsOffset)); |
| 1784 // TODO(jbramley): Can these Operand constructors be implicit? | 1780 // TODO(jbramley): Can these Operand constructors be implicit? |
| 1785 __ Mov(x2, Operand(Smi::FromInt(expr->literal_index()))); | 1781 __ Mov(x2, Operand(Smi::FromInt(expr->literal_index()))); |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1967 break; | 1963 break; |
| 1968 } | 1964 } |
| 1969 } | 1965 } |
| 1970 | 1966 |
| 1971 | 1967 |
| 1972 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 1968 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
| 1973 SetSourcePosition(prop->position()); | 1969 SetSourcePosition(prop->position()); |
| 1974 Literal* key = prop->key()->AsLiteral(); | 1970 Literal* key = prop->key()->AsLiteral(); |
| 1975 __ Mov(x2, Operand(key->value())); | 1971 __ Mov(x2, Operand(key->value())); |
| 1976 // Call load IC. It has arguments receiver and property name x0 and x2. | 1972 // Call load IC. It has arguments receiver and property name x0 and x2. |
| 1977 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1973 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); |
| 1978 CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); | |
| 1979 } | 1974 } |
| 1980 | 1975 |
| 1981 | 1976 |
| 1982 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1977 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
| 1983 SetSourcePosition(prop->position()); | 1978 SetSourcePosition(prop->position()); |
| 1984 // Call keyed load IC. It has arguments key and receiver in r0 and r1. | 1979 // Call keyed load IC. It has arguments key and receiver in r0 and r1. |
| 1985 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 1980 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 1986 CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); | 1981 CallIC(ic, NOT_CONTEXTUAL, prop->PropertyFeedbackId()); |
| 1987 } | 1982 } |
| 1988 | 1983 |
| 1989 | 1984 |
| 1990 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 1985 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
| 1991 Token::Value op, | 1986 Token::Value op, |
| 1992 OverwriteMode mode, | 1987 OverwriteMode mode, |
| 1993 Expression* left_expr, | 1988 Expression* left_expr, |
| 1994 Expression* right_expr) { | 1989 Expression* right_expr) { |
| 1995 Label done, both_smis, stub_call; | 1990 Label done, both_smis, stub_call; |
| 1996 | 1991 |
| 1997 // Get the arguments. | 1992 // Get the arguments. |
| 1998 Register left = x1; | 1993 Register left = x1; |
| 1999 Register right = x0; | 1994 Register right = x0; |
| 2000 Register result = x0; | 1995 Register result = x0; |
| 2001 __ Pop(left); | 1996 __ Pop(left); |
| 2002 | 1997 |
| 2003 // Perform combined smi check on both operands. | 1998 // Perform combined smi check on both operands. |
| 2004 __ Orr(x10, left, right); | 1999 __ Orr(x10, left, right); |
| 2005 JumpPatchSite patch_site(masm_); | 2000 JumpPatchSite patch_site(masm_); |
| 2006 patch_site.EmitJumpIfSmi(x10, &both_smis); | 2001 patch_site.EmitJumpIfSmi(x10, &both_smis); |
| 2007 | 2002 |
| 2008 __ Bind(&stub_call); | 2003 __ Bind(&stub_call); |
| 2009 BinaryOpICStub stub(op, mode); | 2004 BinaryOpICStub stub(op, mode); |
| 2010 { | 2005 { |
| 2011 Assembler::BlockConstPoolScope scope(masm_); | 2006 Assembler::BlockConstPoolScope scope(masm_); |
| 2012 CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, | 2007 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, |
| 2013 expr->BinaryOperationFeedbackId()); | 2008 expr->BinaryOperationFeedbackId()); |
| 2014 patch_site.EmitPatchInfo(); | 2009 patch_site.EmitPatchInfo(); |
| 2015 } | 2010 } |
| 2016 __ B(&done); | 2011 __ B(&done); |
| 2017 | 2012 |
| 2018 __ Bind(&both_smis); | 2013 __ Bind(&both_smis); |
| 2019 // Smi case. This code works in the same way as the smi-smi case in the type | 2014 // Smi case. This code works in the same way as the smi-smi case in the type |
| 2020 // recording binary operation stub, see | 2015 // recording binary operation stub, see |
| 2021 // BinaryOpStub::GenerateSmiSmiOperation for comments. | 2016 // BinaryOpStub::GenerateSmiSmiOperation for comments. |
| 2022 // TODO(all): That doesn't exist any more. Where are the comments? | 2017 // TODO(all): That doesn't exist any more. Where are the comments? |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2089 | 2084 |
| 2090 | 2085 |
| 2091 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, | 2086 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, |
| 2092 Token::Value op, | 2087 Token::Value op, |
| 2093 OverwriteMode mode) { | 2088 OverwriteMode mode) { |
| 2094 __ Pop(x1); | 2089 __ Pop(x1); |
| 2095 BinaryOpICStub stub(op, mode); | 2090 BinaryOpICStub stub(op, mode); |
| 2096 JumpPatchSite patch_site(masm_); // Unbound, signals no inlined smi code. | 2091 JumpPatchSite patch_site(masm_); // Unbound, signals no inlined smi code. |
| 2097 { | 2092 { |
| 2098 Assembler::BlockConstPoolScope scope(masm_); | 2093 Assembler::BlockConstPoolScope scope(masm_); |
| 2099 CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, | 2094 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, |
| 2100 expr->BinaryOperationFeedbackId()); | 2095 expr->BinaryOperationFeedbackId()); |
| 2101 patch_site.EmitPatchInfo(); | 2096 patch_site.EmitPatchInfo(); |
| 2102 } | 2097 } |
| 2103 context()->Plug(x0); | 2098 context()->Plug(x0); |
| 2104 } | 2099 } |
| 2105 | 2100 |
| 2106 | 2101 |
| 2107 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 2102 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
| 2108 // Invalid left-hand sides are rewritten to have a 'throw | 2103 // Invalid left-hand sides are rewritten to have a 'throw |
| 2109 // ReferenceError' on the left-hand side. | 2104 // ReferenceError' on the left-hand side. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2131 break; | 2126 break; |
| 2132 } | 2127 } |
| 2133 case NAMED_PROPERTY: { | 2128 case NAMED_PROPERTY: { |
| 2134 __ Push(x0); // Preserve value. | 2129 __ Push(x0); // Preserve value. |
| 2135 VisitForAccumulatorValue(prop->obj()); | 2130 VisitForAccumulatorValue(prop->obj()); |
| 2136 // TODO(all): We could introduce a VisitForRegValue(reg, expr) to avoid | 2131 // TODO(all): We could introduce a VisitForRegValue(reg, expr) to avoid |
| 2137 // this copy. | 2132 // this copy. |
| 2138 __ Mov(x1, x0); | 2133 __ Mov(x1, x0); |
| 2139 __ Pop(x0); // Restore value. | 2134 __ Pop(x0); // Restore value. |
| 2140 __ Mov(x2, Operand(prop->key()->AsLiteral()->value())); | 2135 __ Mov(x2, Operand(prop->key()->AsLiteral()->value())); |
| 2141 Handle<Code> ic = is_classic_mode() | 2136 CallStoreIC(NOT_CONTEXTUAL); |
| 2142 ? isolate()->builtins()->StoreIC_Initialize() | |
| 2143 : isolate()->builtins()->StoreIC_Initialize_Strict(); | |
| 2144 CallIC(ic); | |
| 2145 break; | 2137 break; |
| 2146 } | 2138 } |
| 2147 case KEYED_PROPERTY: { | 2139 case KEYED_PROPERTY: { |
| 2148 __ Push(x0); // Preserve value. | 2140 __ Push(x0); // Preserve value. |
| 2149 VisitForStackValue(prop->obj()); | 2141 VisitForStackValue(prop->obj()); |
| 2150 VisitForAccumulatorValue(prop->key()); | 2142 VisitForAccumulatorValue(prop->key()); |
| 2151 __ Mov(x1, x0); | 2143 __ Mov(x1, x0); |
| 2152 __ Pop(x2, x0); | 2144 __ Pop(x2, x0); |
| 2153 Handle<Code> ic = is_classic_mode() | 2145 Handle<Code> ic = is_classic_mode() |
| 2154 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2146 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2155 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2147 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2156 CallIC(ic); | 2148 CallIC(ic); |
| 2157 break; | 2149 break; |
| 2158 } | 2150 } |
| 2159 } | 2151 } |
| 2160 context()->Plug(x0); | 2152 context()->Plug(x0); |
| 2161 } | 2153 } |
| 2162 | 2154 |
| 2163 | 2155 |
| 2164 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 2156 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
| 2165 Token::Value op) { | 2157 Token::Value op) { |
| 2166 ASM_LOCATION("FullCodeGenerator::EmitVariableAssignment"); | 2158 ASM_LOCATION("FullCodeGenerator::EmitVariableAssignment"); |
| 2167 if (var->IsUnallocated()) { | 2159 if (var->IsUnallocated()) { |
| 2168 // Global var, const, or let. | 2160 // Global var, const, or let. |
| 2169 __ Mov(x2, Operand(var->name())); | 2161 __ Mov(x2, Operand(var->name())); |
| 2170 __ Ldr(x1, GlobalObjectMemOperand()); | 2162 __ Ldr(x1, GlobalObjectMemOperand()); |
| 2171 Handle<Code> ic = is_classic_mode() | 2163 CallStoreIC(CONTEXTUAL); |
| 2172 ? isolate()->builtins()->StoreIC_Initialize() | |
| 2173 : isolate()->builtins()->StoreIC_Initialize_Strict(); | |
| 2174 CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); | |
| 2175 | 2164 |
| 2176 } else if (op == Token::INIT_CONST) { | 2165 } else if (op == Token::INIT_CONST) { |
| 2177 // Const initializers need a write barrier. | 2166 // Const initializers need a write barrier. |
| 2178 ASSERT(!var->IsParameter()); // No const parameters. | 2167 ASSERT(!var->IsParameter()); // No const parameters. |
| 2179 if (var->IsStackLocal()) { | 2168 if (var->IsStackLocal()) { |
| 2180 Label skip; | 2169 Label skip; |
| 2181 __ Ldr(x1, StackOperand(var)); | 2170 __ Ldr(x1, StackOperand(var)); |
| 2182 __ JumpIfNotRoot(x1, Heap::kTheHoleValueRootIndex, &skip); | 2171 __ JumpIfNotRoot(x1, Heap::kTheHoleValueRootIndex, &skip); |
| 2183 __ Str(result_register(), StackOperand(var)); | 2172 __ Str(result_register(), StackOperand(var)); |
| 2184 __ Bind(&skip); | 2173 __ Bind(&skip); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2263 // Assignment to a property, using a named store IC. | 2252 // Assignment to a property, using a named store IC. |
| 2264 Property* prop = expr->target()->AsProperty(); | 2253 Property* prop = expr->target()->AsProperty(); |
| 2265 ASSERT(prop != NULL); | 2254 ASSERT(prop != NULL); |
| 2266 ASSERT(prop->key()->AsLiteral() != NULL); | 2255 ASSERT(prop->key()->AsLiteral() != NULL); |
| 2267 | 2256 |
| 2268 // Record source code position before IC call. | 2257 // Record source code position before IC call. |
| 2269 SetSourcePosition(expr->position()); | 2258 SetSourcePosition(expr->position()); |
| 2270 __ Mov(x2, Operand(prop->key()->AsLiteral()->value())); | 2259 __ Mov(x2, Operand(prop->key()->AsLiteral()->value())); |
| 2271 __ Pop(x1); | 2260 __ Pop(x1); |
| 2272 | 2261 |
| 2273 Handle<Code> ic = is_classic_mode() | 2262 CallStoreIC(NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); |
| 2274 ? isolate()->builtins()->StoreIC_Initialize() | |
| 2275 : isolate()->builtins()->StoreIC_Initialize_Strict(); | |
| 2276 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); | |
| 2277 | 2263 |
| 2278 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2264 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2279 context()->Plug(x0); | 2265 context()->Plug(x0); |
| 2280 } | 2266 } |
| 2281 | 2267 |
| 2282 | 2268 |
| 2283 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2269 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 2284 ASM_LOCATION("FullCodeGenerator::EmitKeyedPropertyAssignment"); | 2270 ASM_LOCATION("FullCodeGenerator::EmitKeyedPropertyAssignment"); |
| 2285 // Assignment to a property, using a keyed store IC. | 2271 // Assignment to a property, using a keyed store IC. |
| 2286 | 2272 |
| 2287 // Record source code position before IC call. | 2273 // Record source code position before IC call. |
| 2288 SetSourcePosition(expr->position()); | 2274 SetSourcePosition(expr->position()); |
| 2289 // TODO(all): Could we pass this in registers rather than on the stack? | 2275 // TODO(all): Could we pass this in registers rather than on the stack? |
| 2290 __ Pop(x1, x2); // Key and object holding the property. | 2276 __ Pop(x1, x2); // Key and object holding the property. |
| 2291 | 2277 |
| 2292 Handle<Code> ic = is_classic_mode() | 2278 Handle<Code> ic = is_classic_mode() |
| 2293 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2279 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2294 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2280 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2295 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); | 2281 CallIC(ic, NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); |
| 2296 | 2282 |
| 2297 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2283 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2298 context()->Plug(x0); | 2284 context()->Plug(x0); |
| 2299 } | 2285 } |
| 2300 | 2286 |
| 2301 | 2287 |
| 2302 void FullCodeGenerator::VisitProperty(Property* expr) { | 2288 void FullCodeGenerator::VisitProperty(Property* expr) { |
| 2303 Comment cmnt(masm_, "[ Property"); | 2289 Comment cmnt(masm_, "[ Property"); |
| 2304 Expression* key = expr->key(); | 2290 Expression* key = expr->key(); |
| 2305 | 2291 |
| 2306 if (key->IsPropertyName()) { | 2292 if (key->IsPropertyName()) { |
| 2307 VisitForAccumulatorValue(expr->obj()); | 2293 VisitForAccumulatorValue(expr->obj()); |
| 2308 EmitNamedPropertyLoad(expr); | 2294 EmitNamedPropertyLoad(expr); |
| 2309 PrepareForBailoutForId(expr->LoadId(), TOS_REG); | 2295 PrepareForBailoutForId(expr->LoadId(), TOS_REG); |
| 2310 context()->Plug(x0); | 2296 context()->Plug(x0); |
| 2311 } else { | 2297 } else { |
| 2312 VisitForStackValue(expr->obj()); | 2298 VisitForStackValue(expr->obj()); |
| 2313 VisitForAccumulatorValue(expr->key()); | 2299 VisitForAccumulatorValue(expr->key()); |
| 2314 __ Pop(x1); | 2300 __ Pop(x1); |
| 2315 EmitKeyedPropertyLoad(expr); | 2301 EmitKeyedPropertyLoad(expr); |
| 2316 context()->Plug(x0); | 2302 context()->Plug(x0); |
| 2317 } | 2303 } |
| 2318 } | 2304 } |
| 2319 | 2305 |
| 2320 | 2306 |
| 2321 void FullCodeGenerator::CallIC(Handle<Code> code, | 2307 void FullCodeGenerator::CallIC(Handle<Code> code, |
| 2322 RelocInfo::Mode rmode, | 2308 ContextualMode mode, |
| 2323 TypeFeedbackId ast_id) { | 2309 TypeFeedbackId ast_id) { |
| 2324 ic_total_count_++; | 2310 ic_total_count_++; |
| 2325 // All calls must have a predictable size in full-codegen code to ensure that | 2311 // All calls must have a predictable size in full-codegen code to ensure that |
| 2326 // the debugger can patch them correctly. | 2312 // the debugger can patch them correctly. |
| 2327 __ Call(code, rmode, ast_id); | 2313 ASSERT((mode != CONTEXTUAL) || ast_id.IsNone()); |
| 2314 __ Call(code, RelocInfo::CODE_TARGET, ast_id); |
| 2328 } | 2315 } |
| 2329 | 2316 |
| 2330 | 2317 |
| 2331 void FullCodeGenerator::EmitCallWithIC(Call* expr, | 2318 void FullCodeGenerator::EmitCallWithIC(Call* expr, |
| 2332 Handle<Object> name, | 2319 Handle<Object> name, |
| 2333 RelocInfo::Mode mode) { | 2320 ContextualMode mode) { |
| 2334 ASM_LOCATION("EmitCallWithIC"); | 2321 ASM_LOCATION("EmitCallWithIC"); |
| 2335 // Code common for calls using the IC. | 2322 // Code common for calls using the IC. |
| 2336 ZoneList<Expression*>* args = expr->arguments(); | 2323 ZoneList<Expression*>* args = expr->arguments(); |
| 2337 int arg_count = args->length(); | 2324 int arg_count = args->length(); |
| 2338 { PreservePositionScope scope(masm()->positions_recorder()); | 2325 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2339 for (int i = 0; i < arg_count; i++) { | 2326 for (int i = 0; i < arg_count; i++) { |
| 2340 VisitForStackValue(args->at(i)); | 2327 VisitForStackValue(args->at(i)); |
| 2341 } | 2328 } |
| 2342 __ Mov(x2, Operand(name)); | 2329 __ Mov(x2, Operand(name)); |
| 2343 } | 2330 } |
| 2344 // Record source position for debugger. | 2331 // Record source position for debugger. |
| 2345 SetSourcePosition(expr->position()); | 2332 SetSourcePosition(expr->position()); |
| 2346 // Call the IC initialization code. | 2333 // Call the IC initialization code. |
| 2347 Handle<Code> ic = | 2334 Handle<Code> ic = |
| 2348 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); | 2335 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); |
| 2349 CallIC(ic, mode, expr->CallFeedbackId()); | 2336 TypeFeedbackId ast_id = mode == CONTEXTUAL |
| 2337 ? TypeFeedbackId::None() |
| 2338 : expr->CallFeedbackId(); |
| 2339 CallIC(ic, mode, ast_id); |
| 2350 RecordJSReturnSite(expr); | 2340 RecordJSReturnSite(expr); |
| 2351 // Restore context register. | 2341 // Restore context register. |
| 2352 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2342 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2353 context()->Plug(x0); | 2343 context()->Plug(x0); |
| 2354 } | 2344 } |
| 2355 | 2345 |
| 2356 | 2346 |
| 2357 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2347 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
| 2358 Expression* key) { | 2348 Expression* key) { |
| 2359 // Load the key. | 2349 // Load the key. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2372 for (int i = 0; i < arg_count; i++) { | 2362 for (int i = 0; i < arg_count; i++) { |
| 2373 VisitForStackValue(args->at(i)); | 2363 VisitForStackValue(args->at(i)); |
| 2374 } | 2364 } |
| 2375 } | 2365 } |
| 2376 // Record source position for debugger. | 2366 // Record source position for debugger. |
| 2377 SetSourcePosition(expr->position()); | 2367 SetSourcePosition(expr->position()); |
| 2378 // Call the IC initialization code. | 2368 // Call the IC initialization code. |
| 2379 Handle<Code> ic = | 2369 Handle<Code> ic = |
| 2380 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); | 2370 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); |
| 2381 __ Peek(x2, (arg_count + 1) * kXRegSizeInBytes); // Key. | 2371 __ Peek(x2, (arg_count + 1) * kXRegSizeInBytes); // Key. |
| 2382 CallIC(ic, RelocInfo::CODE_TARGET, expr->CallFeedbackId()); | 2372 CallIC(ic, NOT_CONTEXTUAL, expr->CallFeedbackId()); |
| 2383 RecordJSReturnSite(expr); | 2373 RecordJSReturnSite(expr); |
| 2384 // Restore context register. | 2374 // Restore context register. |
| 2385 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2375 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2386 context()->DropAndPlug(1, x0); // Drop the key still on the stack. | 2376 context()->DropAndPlug(1, x0); // Drop the key still on the stack. |
| 2387 } | 2377 } |
| 2388 | 2378 |
| 2389 | 2379 |
| 2390 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { | 2380 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { |
| 2391 // Code common for calls using the call stub. | 2381 // Code common for calls using the call stub. |
| 2392 ZoneList<Expression*>* args = expr->arguments(); | 2382 ZoneList<Expression*>* args = expr->arguments(); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2487 | 2477 |
| 2488 // The runtime call returns a pair of values in x0 (function) and | 2478 // The runtime call returns a pair of values in x0 (function) and |
| 2489 // x1 (receiver). Touch up the stack with the right values. | 2479 // x1 (receiver). Touch up the stack with the right values. |
| 2490 __ PokePair(x1, x0, arg_count * kPointerSize); | 2480 __ PokePair(x1, x0, arg_count * kPointerSize); |
| 2491 } | 2481 } |
| 2492 | 2482 |
| 2493 // Record source position for debugger. | 2483 // Record source position for debugger. |
| 2494 SetSourcePosition(expr->position()); | 2484 SetSourcePosition(expr->position()); |
| 2495 | 2485 |
| 2496 // Call the evaluated function. | 2486 // Call the evaluated function. |
| 2497 CallFunctionStub stub(arg_count, RECEIVER_MIGHT_BE_IMPLICIT); | 2487 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS); |
| 2498 __ Peek(x1, (arg_count + 1) * kXRegSizeInBytes); | 2488 __ Peek(x1, (arg_count + 1) * kXRegSizeInBytes); |
| 2499 __ CallStub(&stub); | 2489 __ CallStub(&stub); |
| 2500 RecordJSReturnSite(expr); | 2490 RecordJSReturnSite(expr); |
| 2501 // Restore context register. | 2491 // Restore context register. |
| 2502 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2492 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2503 context()->DropAndPlug(1, x0); | 2493 context()->DropAndPlug(1, x0); |
| 2504 | 2494 |
| 2505 } else if (proxy != NULL && proxy->var()->IsUnallocated()) { | 2495 } else if (proxy != NULL && proxy->var()->IsUnallocated()) { |
| 2506 // Push global object as receiver for the call IC. | 2496 // Push global object as receiver for the call IC. |
| 2507 __ Ldr(x10, GlobalObjectMemOperand()); | 2497 __ Ldr(x10, GlobalObjectMemOperand()); |
| 2508 __ Push(x10); | 2498 __ Push(x10); |
| 2509 EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT); | 2499 EmitCallWithIC(expr, proxy->name(), CONTEXTUAL); |
| 2510 | 2500 |
| 2511 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { | 2501 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { |
| 2512 // Call to a lookup slot (dynamically introduced variable). | 2502 // Call to a lookup slot (dynamically introduced variable). |
| 2513 Label slow, done; | 2503 Label slow, done; |
| 2514 | 2504 |
| 2515 { PreservePositionScope scope(masm()->positions_recorder()); | 2505 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2516 // Generate code for loading from variables potentially shadowed | 2506 // Generate code for loading from variables potentially shadowed |
| 2517 // by eval-introduced variables. | 2507 // by eval-introduced variables. |
| 2518 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); | 2508 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); |
| 2519 } | 2509 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2530 // If fast case code has been generated, emit code to push the | 2520 // If fast case code has been generated, emit code to push the |
| 2531 // function and receiver and have the slow path jump around this | 2521 // function and receiver and have the slow path jump around this |
| 2532 // code. | 2522 // code. |
| 2533 if (done.is_linked()) { | 2523 if (done.is_linked()) { |
| 2534 Label call; | 2524 Label call; |
| 2535 __ B(&call); | 2525 __ B(&call); |
| 2536 __ Bind(&done); | 2526 __ Bind(&done); |
| 2537 // Push function. | 2527 // Push function. |
| 2538 __ Push(x0); | 2528 __ Push(x0); |
| 2539 // The receiver is implicitly the global receiver. Indicate this | 2529 // The receiver is implicitly the global receiver. Indicate this |
| 2540 // by passing the hole to the call function stub. | 2530 // by passing the undefined to the call function stub. |
| 2541 __ LoadRoot(x1, Heap::kTheHoleValueRootIndex); | 2531 __ LoadRoot(x1, Heap::kUndefinedValueRootIndex); |
| 2542 __ Push(x1); | 2532 __ Push(x1); |
| 2543 __ Bind(&call); | 2533 __ Bind(&call); |
| 2544 } | 2534 } |
| 2545 | 2535 |
| 2546 // The receiver is either the global receiver or an object found | 2536 // The receiver is either the global receiver or an object found |
| 2547 // by LoadContextSlot. That object could be the hole if the | 2537 // by LoadContextSlot. |
| 2548 // receiver is implicitly the global object. | 2538 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); |
| 2549 EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT); | |
| 2550 } else if (property != NULL) { | 2539 } else if (property != NULL) { |
| 2551 { PreservePositionScope scope(masm()->positions_recorder()); | 2540 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2552 VisitForStackValue(property->obj()); | 2541 VisitForStackValue(property->obj()); |
| 2553 } | 2542 } |
| 2554 if (property->key()->IsPropertyName()) { | 2543 if (property->key()->IsPropertyName()) { |
| 2555 EmitCallWithIC(expr, | 2544 EmitCallWithIC(expr, |
| 2556 property->key()->AsLiteral()->value(), | 2545 property->key()->AsLiteral()->value(), |
| 2557 RelocInfo::CODE_TARGET); | 2546 NOT_CONTEXTUAL); |
| 2558 } else { | 2547 } else { |
| 2559 EmitKeyedCallWithIC(expr, property->key()); | 2548 EmitKeyedCallWithIC(expr, property->key()); |
| 2560 } | 2549 } |
| 2561 | 2550 |
| 2562 } else { | 2551 } else { |
| 2563 // Call to an arbitrary expression not handled specially above. | 2552 // Call to an arbitrary expression not handled specially above. |
| 2564 { PreservePositionScope scope(masm()->positions_recorder()); | 2553 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2565 VisitForStackValue(callee); | 2554 VisitForStackValue(callee); |
| 2566 } | 2555 } |
| 2567 // Load global receiver object. | 2556 __ LoadRoot(x1, Heap::kUndefinedValueRootIndex); |
| 2568 __ Ldr(x1, GlobalObjectMemOperand()); | |
| 2569 __ Ldr(x1, FieldMemOperand(x1, GlobalObject::kGlobalReceiverOffset)); | |
| 2570 __ Push(x1); | 2557 __ Push(x1); |
| 2571 // Emit function call. | 2558 // Emit function call. |
| 2572 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); | 2559 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); |
| 2573 } | 2560 } |
| 2574 | 2561 |
| 2575 #ifdef DEBUG | 2562 #ifdef DEBUG |
| 2576 // RecordJSReturnSite should have been called. | 2563 // RecordJSReturnSite should have been called. |
| 2577 ASSERT(expr->return_is_recorded_); | 2564 ASSERT(expr->return_is_recorded_); |
| 2578 #endif | 2565 #endif |
| 2579 } | 2566 } |
| (...skipping 926 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3506 | 3493 |
| 3507 Label runtime, done; | 3494 Label runtime, done; |
| 3508 // Check for non-function argument (including proxy). | 3495 // Check for non-function argument (including proxy). |
| 3509 __ JumpIfSmi(x0, &runtime); | 3496 __ JumpIfSmi(x0, &runtime); |
| 3510 __ JumpIfNotObjectType(x0, x1, x1, JS_FUNCTION_TYPE, &runtime); | 3497 __ JumpIfNotObjectType(x0, x1, x1, JS_FUNCTION_TYPE, &runtime); |
| 3511 | 3498 |
| 3512 // InvokeFunction requires the function in x1. Move it in there. | 3499 // InvokeFunction requires the function in x1. Move it in there. |
| 3513 __ Mov(x1, x0); | 3500 __ Mov(x1, x0); |
| 3514 ParameterCount count(arg_count); | 3501 ParameterCount count(arg_count); |
| 3515 __ InvokeFunction(x1, count, CALL_FUNCTION, | 3502 __ InvokeFunction(x1, count, CALL_FUNCTION, |
| 3516 NullCallWrapper(), CALL_AS_METHOD); | 3503 NullCallWrapper(), CALL_AS_FUNCTION); |
| 3517 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3504 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 3518 __ B(&done); | 3505 __ B(&done); |
| 3519 | 3506 |
| 3520 __ Bind(&runtime); | 3507 __ Bind(&runtime); |
| 3521 __ Push(x0); | 3508 __ Push(x0); |
| 3522 __ CallRuntime(Runtime::kCall, args->length()); | 3509 __ CallRuntime(Runtime::kCall, args->length()); |
| 3523 __ Bind(&done); | 3510 __ Bind(&done); |
| 3524 | 3511 |
| 3525 context()->Plug(x0); | 3512 context()->Plug(x0); |
| 3526 } | 3513 } |
| (...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3904 } | 3891 } |
| 3905 | 3892 |
| 3906 int arg_count = args->length(); | 3893 int arg_count = args->length(); |
| 3907 for (int i = 0; i < arg_count; i++) { | 3894 for (int i = 0; i < arg_count; i++) { |
| 3908 VisitForStackValue(args->at(i)); | 3895 VisitForStackValue(args->at(i)); |
| 3909 } | 3896 } |
| 3910 | 3897 |
| 3911 if (expr->is_jsruntime()) { | 3898 if (expr->is_jsruntime()) { |
| 3912 // Call the JS runtime function. | 3899 // Call the JS runtime function. |
| 3913 __ Mov(x2, Operand(expr->name())); | 3900 __ Mov(x2, Operand(expr->name())); |
| 3914 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; | 3901 ContextualMode mode = NOT_CONTEXTUAL; |
| 3915 Handle<Code> ic = | 3902 Handle<Code> ic = |
| 3916 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); | 3903 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); |
| 3917 CallIC(ic, mode, expr->CallRuntimeFeedbackId()); | 3904 CallIC(ic, mode, expr->CallRuntimeFeedbackId()); |
| 3918 // Restore context register. | 3905 // Restore context register. |
| 3919 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3906 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 3920 } else { | 3907 } else { |
| 3921 // Call the C runtime function. | 3908 // Call the C runtime function. |
| 3922 __ CallRuntime(expr->function(), arg_count); | 3909 __ CallRuntime(expr->function(), arg_count); |
| 3923 } | 3910 } |
| 3924 | 3911 |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4156 __ Bind(&stub_call); | 4143 __ Bind(&stub_call); |
| 4157 __ Mov(x1, x0); | 4144 __ Mov(x1, x0); |
| 4158 __ Mov(x0, Operand(Smi::FromInt(count_value))); | 4145 __ Mov(x0, Operand(Smi::FromInt(count_value))); |
| 4159 | 4146 |
| 4160 // Record position before stub call. | 4147 // Record position before stub call. |
| 4161 SetSourcePosition(expr->position()); | 4148 SetSourcePosition(expr->position()); |
| 4162 | 4149 |
| 4163 { | 4150 { |
| 4164 Assembler::BlockConstPoolScope scope(masm_); | 4151 Assembler::BlockConstPoolScope scope(masm_); |
| 4165 BinaryOpICStub stub(Token::ADD, NO_OVERWRITE); | 4152 BinaryOpICStub stub(Token::ADD, NO_OVERWRITE); |
| 4166 CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, | 4153 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, |
| 4167 expr->CountBinOpFeedbackId()); | 4154 expr->CountBinOpFeedbackId()); |
| 4168 patch_site.EmitPatchInfo(); | 4155 patch_site.EmitPatchInfo(); |
| 4169 } | 4156 } |
| 4170 __ Bind(&done); | 4157 __ Bind(&done); |
| 4171 | 4158 |
| 4172 // Store the value returned in x0. | 4159 // Store the value returned in x0. |
| 4173 switch (assign_type) { | 4160 switch (assign_type) { |
| 4174 case VARIABLE: | 4161 case VARIABLE: |
| 4175 if (expr->is_postfix()) { | 4162 if (expr->is_postfix()) { |
| 4176 { EffectContext context(this); | 4163 { EffectContext context(this); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4187 } else { | 4174 } else { |
| 4188 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 4175 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 4189 Token::ASSIGN); | 4176 Token::ASSIGN); |
| 4190 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4177 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4191 context()->Plug(x0); | 4178 context()->Plug(x0); |
| 4192 } | 4179 } |
| 4193 break; | 4180 break; |
| 4194 case NAMED_PROPERTY: { | 4181 case NAMED_PROPERTY: { |
| 4195 __ Mov(x2, Operand(prop->key()->AsLiteral()->value())); | 4182 __ Mov(x2, Operand(prop->key()->AsLiteral()->value())); |
| 4196 __ Pop(x1); | 4183 __ Pop(x1); |
| 4197 Handle<Code> ic = is_classic_mode() | 4184 CallStoreIC(NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); |
| 4198 ? isolate()->builtins()->StoreIC_Initialize() | |
| 4199 : isolate()->builtins()->StoreIC_Initialize_Strict(); | |
| 4200 CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); | |
| 4201 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4185 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4202 if (expr->is_postfix()) { | 4186 if (expr->is_postfix()) { |
| 4203 if (!context()->IsEffect()) { | 4187 if (!context()->IsEffect()) { |
| 4204 context()->PlugTOS(); | 4188 context()->PlugTOS(); |
| 4205 } | 4189 } |
| 4206 } else { | 4190 } else { |
| 4207 context()->Plug(x0); | 4191 context()->Plug(x0); |
| 4208 } | 4192 } |
| 4209 break; | 4193 break; |
| 4210 } | 4194 } |
| 4211 case KEYED_PROPERTY: { | 4195 case KEYED_PROPERTY: { |
| 4212 __ Pop(x1); // Key. | 4196 __ Pop(x1); // Key. |
| 4213 __ Pop(x2); // Receiver. | 4197 __ Pop(x2); // Receiver. |
| 4214 Handle<Code> ic = is_classic_mode() | 4198 Handle<Code> ic = is_classic_mode() |
| 4215 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 4199 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 4216 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 4200 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 4217 CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); | 4201 CallIC(ic, NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); |
| 4218 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4202 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4219 if (expr->is_postfix()) { | 4203 if (expr->is_postfix()) { |
| 4220 if (!context()->IsEffect()) { | 4204 if (!context()->IsEffect()) { |
| 4221 context()->PlugTOS(); | 4205 context()->PlugTOS(); |
| 4222 } | 4206 } |
| 4223 } else { | 4207 } else { |
| 4224 context()->Plug(x0); | 4208 context()->Plug(x0); |
| 4225 } | 4209 } |
| 4226 break; | 4210 break; |
| 4227 } | 4211 } |
| 4228 } | 4212 } |
| 4229 } | 4213 } |
| 4230 | 4214 |
| 4231 | 4215 |
| 4232 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | 4216 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { |
| 4233 ASSERT(!context()->IsEffect()); | 4217 ASSERT(!context()->IsEffect()); |
| 4234 ASSERT(!context()->IsTest()); | 4218 ASSERT(!context()->IsTest()); |
| 4235 VariableProxy* proxy = expr->AsVariableProxy(); | 4219 VariableProxy* proxy = expr->AsVariableProxy(); |
| 4236 if (proxy != NULL && proxy->var()->IsUnallocated()) { | 4220 if (proxy != NULL && proxy->var()->IsUnallocated()) { |
| 4237 Comment cmnt(masm_, "Global variable"); | 4221 Comment cmnt(masm_, "Global variable"); |
| 4238 __ Ldr(x0, GlobalObjectMemOperand()); | 4222 __ Ldr(x0, GlobalObjectMemOperand()); |
| 4239 __ Mov(x2, Operand(proxy->name())); | 4223 __ Mov(x2, Operand(proxy->name())); |
| 4240 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | |
| 4241 // Use a regular load, not a contextual load, to avoid a reference | 4224 // Use a regular load, not a contextual load, to avoid a reference |
| 4242 // error. | 4225 // error. |
| 4243 CallIC(ic); | 4226 CallLoadIC(NOT_CONTEXTUAL); |
| 4244 PrepareForBailout(expr, TOS_REG); | 4227 PrepareForBailout(expr, TOS_REG); |
| 4245 context()->Plug(x0); | 4228 context()->Plug(x0); |
| 4246 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { | 4229 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { |
| 4247 Label done, slow; | 4230 Label done, slow; |
| 4248 | 4231 |
| 4249 // Generate code for loading from variables potentially shadowed | 4232 // Generate code for loading from variables potentially shadowed |
| 4250 // by eval-introduced variables. | 4233 // by eval-introduced variables. |
| 4251 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); | 4234 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); |
| 4252 | 4235 |
| 4253 __ Bind(&slow); | 4236 __ Bind(&slow); |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4405 Label slow_case; | 4388 Label slow_case; |
| 4406 patch_site.EmitJumpIfEitherNotSmi(x0, x1, &slow_case); | 4389 patch_site.EmitJumpIfEitherNotSmi(x0, x1, &slow_case); |
| 4407 __ Cmp(x1, x0); | 4390 __ Cmp(x1, x0); |
| 4408 Split(cond, if_true, if_false, NULL); | 4391 Split(cond, if_true, if_false, NULL); |
| 4409 __ Bind(&slow_case); | 4392 __ Bind(&slow_case); |
| 4410 } | 4393 } |
| 4411 | 4394 |
| 4412 // Record position and call the compare IC. | 4395 // Record position and call the compare IC. |
| 4413 SetSourcePosition(expr->position()); | 4396 SetSourcePosition(expr->position()); |
| 4414 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 4397 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
| 4415 CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); | 4398 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); |
| 4416 patch_site.EmitPatchInfo(); | 4399 patch_site.EmitPatchInfo(); |
| 4417 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 4400 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 4418 __ CompareAndSplit(x0, 0, cond, if_true, if_false, fall_through); | 4401 __ CompareAndSplit(x0, 0, cond, if_true, if_false, fall_through); |
| 4419 } | 4402 } |
| 4420 } | 4403 } |
| 4421 | 4404 |
| 4422 // Convert the result of the comparison into one expected for this | 4405 // Convert the result of the comparison into one expected for this |
| 4423 // expression's context. | 4406 // expression's context. |
| 4424 context()->Plug(if_true, if_false); | 4407 context()->Plug(if_true, if_false); |
| 4425 } | 4408 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4440 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 4423 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 4441 | 4424 |
| 4442 if (expr->op() == Token::EQ_STRICT) { | 4425 if (expr->op() == Token::EQ_STRICT) { |
| 4443 Heap::RootListIndex nil_value = nil == kNullValue ? | 4426 Heap::RootListIndex nil_value = nil == kNullValue ? |
| 4444 Heap::kNullValueRootIndex : | 4427 Heap::kNullValueRootIndex : |
| 4445 Heap::kUndefinedValueRootIndex; | 4428 Heap::kUndefinedValueRootIndex; |
| 4446 __ CompareRoot(x0, nil_value); | 4429 __ CompareRoot(x0, nil_value); |
| 4447 Split(eq, if_true, if_false, fall_through); | 4430 Split(eq, if_true, if_false, fall_through); |
| 4448 } else { | 4431 } else { |
| 4449 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); | 4432 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); |
| 4450 CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); | 4433 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); |
| 4451 __ CompareAndSplit(x0, 0, ne, if_true, if_false, fall_through); | 4434 __ CompareAndSplit(x0, 0, ne, if_true, if_false, fall_through); |
| 4452 } | 4435 } |
| 4453 | 4436 |
| 4454 context()->Plug(if_true, if_false); | 4437 context()->Plug(if_true, if_false); |
| 4455 } | 4438 } |
| 4456 | 4439 |
| 4457 | 4440 |
| 4458 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 4441 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
| 4459 __ Ldr(x0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 4442 __ Ldr(x0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 4460 context()->Plug(x0); | 4443 context()->Plug(x0); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4590 // result = receiver[f](arg); | 4573 // result = receiver[f](arg); |
| 4591 __ Bind(&l_call); | 4574 __ Bind(&l_call); |
| 4592 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); | 4575 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); |
| 4593 CallIC(ic); | 4576 CallIC(ic); |
| 4594 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4577 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 4595 | 4578 |
| 4596 // if (!result.done) goto l_try; | 4579 // if (!result.done) goto l_try; |
| 4597 __ Bind(&l_loop); | 4580 __ Bind(&l_loop); |
| 4598 __ Push(x0); // save result | 4581 __ Push(x0); // save result |
| 4599 __ LoadRoot(x2, Heap::kdone_stringRootIndex); // "done" | 4582 __ LoadRoot(x2, Heap::kdone_stringRootIndex); // "done" |
| 4600 Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize(); | 4583 CallLoadIC(NOT_CONTEXTUAL); // result.done in x0 |
| 4601 CallIC(done_ic); // result.done in x0 | |
| 4602 // The ToBooleanStub argument (result.done) is in x0. | 4584 // The ToBooleanStub argument (result.done) is in x0. |
| 4603 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); | 4585 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); |
| 4604 CallIC(bool_ic); | 4586 CallIC(bool_ic); |
| 4605 __ Cbz(x0, &l_try); | 4587 __ Cbz(x0, &l_try); |
| 4606 | 4588 |
| 4607 // result.value | 4589 // result.value |
| 4608 __ Pop(x0); // result | 4590 __ Pop(x0); // result |
| 4609 __ LoadRoot(x2, Heap::kvalue_stringRootIndex); // "value" | 4591 __ LoadRoot(x2, Heap::kvalue_stringRootIndex); // "value" |
| 4610 Handle<Code> value_ic = isolate()->builtins()->LoadIC_Initialize(); | 4592 CallLoadIC(NOT_CONTEXTUAL); // result.value in x0 |
| 4611 CallIC(value_ic); // result.value in x0 | |
| 4612 context()->DropAndPlug(2, x0); // drop iter and g | 4593 context()->DropAndPlug(2, x0); // drop iter and g |
| 4613 break; | 4594 break; |
| 4614 } | 4595 } |
| 4615 } | 4596 } |
| 4616 } | 4597 } |
| 4617 | 4598 |
| 4618 | 4599 |
| 4619 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, | 4600 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, |
| 4620 Expression *value, | 4601 Expression *value, |
| 4621 JSGeneratorObject::ResumeMode resume_mode) { | 4602 JSGeneratorObject::ResumeMode resume_mode) { |
| (...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5025 return previous_; | 5006 return previous_; |
| 5026 } | 5007 } |
| 5027 | 5008 |
| 5028 | 5009 |
| 5029 #undef __ | 5010 #undef __ |
| 5030 | 5011 |
| 5031 | 5012 |
| 5032 } } // namespace v8::internal | 5013 } } // namespace v8::internal |
| 5033 | 5014 |
| 5034 #endif // V8_TARGET_ARCH_A64 | 5015 #endif // V8_TARGET_ARCH_A64 |
| OLD | NEW |