| 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 1612 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1623 __ LoadRoot(x10, Heap::kNullValueRootIndex); | 1623 __ LoadRoot(x10, Heap::kNullValueRootIndex); |
| 1624 __ Push(x10); | 1624 __ Push(x10); |
| 1625 } else { | 1625 } else { |
| 1626 VisitForStackValue(expression); | 1626 VisitForStackValue(expression); |
| 1627 } | 1627 } |
| 1628 } | 1628 } |
| 1629 | 1629 |
| 1630 | 1630 |
| 1631 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 1631 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
| 1632 Comment cmnt(masm_, "[ ObjectLiteral"); | 1632 Comment cmnt(masm_, "[ ObjectLiteral"); |
| 1633 |
| 1634 int depth = 1; |
| 1635 expr->BuildConstantProperties(isolate(), &depth); |
| 1633 Handle<FixedArray> constant_properties = expr->constant_properties(); | 1636 Handle<FixedArray> constant_properties = expr->constant_properties(); |
| 1634 __ Ldr(x3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1637 __ Ldr(x3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1635 __ Ldr(x3, FieldMemOperand(x3, JSFunction::kLiteralsOffset)); | 1638 __ Ldr(x3, FieldMemOperand(x3, JSFunction::kLiteralsOffset)); |
| 1636 __ Mov(x2, Operand(Smi::FromInt(expr->literal_index()))); | 1639 __ Mov(x2, Operand(Smi::FromInt(expr->literal_index()))); |
| 1637 __ Mov(x1, Operand(constant_properties)); | 1640 __ Mov(x1, Operand(constant_properties)); |
| 1638 int flags = expr->fast_elements() | 1641 int flags = expr->fast_elements() |
| 1639 ? ObjectLiteral::kFastElements | 1642 ? ObjectLiteral::kFastElements |
| 1640 : ObjectLiteral::kNoFlags; | 1643 : ObjectLiteral::kNoFlags; |
| 1641 flags |= expr->has_function() | 1644 flags |= expr->has_function() |
| 1642 ? ObjectLiteral::kHasFunction | 1645 ? ObjectLiteral::kHasFunction |
| 1643 : ObjectLiteral::kNoFlags; | 1646 : ObjectLiteral::kNoFlags; |
| 1644 __ Mov(x0, Operand(Smi::FromInt(flags))); | 1647 __ Mov(x0, Operand(Smi::FromInt(flags))); |
| 1645 int properties_count = constant_properties->length() / 2; | 1648 int properties_count = constant_properties->length() / 2; |
| 1646 const int max_cloned_properties = | 1649 const int max_cloned_properties = |
| 1647 FastCloneShallowObjectStub::kMaximumClonedProperties; | 1650 FastCloneShallowObjectStub::kMaximumClonedProperties; |
| 1648 if ((FLAG_track_double_fields && expr->may_store_doubles()) || | 1651 if ((FLAG_track_double_fields && expr->may_store_doubles()) || |
| 1649 (expr->depth() > 1 || Serializer::enabled()) || | 1652 (depth > 1) || Serializer::enabled() || |
| 1650 (flags != ObjectLiteral::kFastElements) || | 1653 (flags != ObjectLiteral::kFastElements) || |
| 1651 (properties_count > max_cloned_properties)) { | 1654 (properties_count > max_cloned_properties)) { |
| 1652 __ Push(x3, x2, x1, x0); | 1655 __ Push(x3, x2, x1, x0); |
| 1653 __ CallRuntime(Runtime::kCreateObjectLiteral, 4); | 1656 __ CallRuntime(Runtime::kCreateObjectLiteral, 4); |
| 1654 } else { | 1657 } else { |
| 1655 FastCloneShallowObjectStub stub(properties_count); | 1658 FastCloneShallowObjectStub stub(properties_count); |
| 1656 __ CallStub(&stub); | 1659 __ CallStub(&stub); |
| 1657 } | 1660 } |
| 1658 | 1661 |
| 1659 // If result_saved is true the result is on top of the stack. If | 1662 // If result_saved is true the result is on top of the stack. If |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1759 context()->PlugTOS(); | 1762 context()->PlugTOS(); |
| 1760 } else { | 1763 } else { |
| 1761 context()->Plug(x0); | 1764 context()->Plug(x0); |
| 1762 } | 1765 } |
| 1763 } | 1766 } |
| 1764 | 1767 |
| 1765 | 1768 |
| 1766 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 1769 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
| 1767 Comment cmnt(masm_, "[ ArrayLiteral"); | 1770 Comment cmnt(masm_, "[ ArrayLiteral"); |
| 1768 | 1771 |
| 1772 int depth = 1; |
| 1773 expr->BuildConstantElements(isolate(), &depth); |
| 1769 ZoneList<Expression*>* subexprs = expr->values(); | 1774 ZoneList<Expression*>* subexprs = expr->values(); |
| 1770 int length = subexprs->length(); | 1775 int length = subexprs->length(); |
| 1771 Handle<FixedArray> constant_elements = expr->constant_elements(); | 1776 Handle<FixedArray> constant_elements = expr->constant_elements(); |
| 1772 ASSERT_EQ(2, constant_elements->length()); | 1777 ASSERT_EQ(2, constant_elements->length()); |
| 1773 ElementsKind constant_elements_kind = | 1778 ElementsKind constant_elements_kind = |
| 1774 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); | 1779 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); |
| 1775 bool has_fast_elements = IsFastObjectElementsKind(constant_elements_kind); | 1780 bool has_fast_elements = IsFastObjectElementsKind(constant_elements_kind); |
| 1776 Handle<FixedArrayBase> constant_elements_values( | 1781 Handle<FixedArrayBase> constant_elements_values( |
| 1777 FixedArrayBase::cast(constant_elements->get(1))); | 1782 FixedArrayBase::cast(constant_elements->get(1))); |
| 1778 | 1783 |
| 1779 __ Ldr(x3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1784 __ Ldr(x3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1780 __ Ldr(x3, FieldMemOperand(x3, JSFunction::kLiteralsOffset)); | 1785 __ Ldr(x3, FieldMemOperand(x3, JSFunction::kLiteralsOffset)); |
| 1781 // TODO(jbramley): Can these Operand constructors be implicit? | 1786 // TODO(jbramley): Can these Operand constructors be implicit? |
| 1782 __ Mov(x2, Operand(Smi::FromInt(expr->literal_index()))); | 1787 __ Mov(x2, Operand(Smi::FromInt(expr->literal_index()))); |
| 1783 __ Mov(x1, Operand(constant_elements)); | 1788 __ Mov(x1, Operand(constant_elements)); |
| 1784 if (has_fast_elements && constant_elements_values->map() == | 1789 if (has_fast_elements && constant_elements_values->map() == |
| 1785 isolate()->heap()->fixed_cow_array_map()) { | 1790 isolate()->heap()->fixed_cow_array_map()) { |
| 1786 FastCloneShallowArrayStub stub( | 1791 FastCloneShallowArrayStub stub( |
| 1787 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, | 1792 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, |
| 1788 DONT_TRACK_ALLOCATION_SITE, | 1793 DONT_TRACK_ALLOCATION_SITE, |
| 1789 length); | 1794 length); |
| 1790 __ CallStub(&stub); | 1795 __ CallStub(&stub); |
| 1791 __ IncrementCounter( | 1796 __ IncrementCounter( |
| 1792 isolate()->counters()->cow_arrays_created_stub(), 1, x10, x11); | 1797 isolate()->counters()->cow_arrays_created_stub(), 1, x10, x11); |
| 1793 } else if (expr->depth() > 1 || | 1798 } else if ((depth > 1) || Serializer::enabled() || |
| 1794 Serializer::enabled() || | |
| 1795 length > FastCloneShallowArrayStub::kMaximumClonedLength) { | 1799 length > FastCloneShallowArrayStub::kMaximumClonedLength) { |
| 1796 __ Push(x3, x2, x1); | 1800 __ Push(x3, x2, x1); |
| 1797 __ CallRuntime(Runtime::kCreateArrayLiteral, 3); | 1801 __ CallRuntime(Runtime::kCreateArrayLiteral, 3); |
| 1798 } else { | 1802 } else { |
| 1799 ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) || | 1803 ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) || |
| 1800 FLAG_smi_only_arrays); | 1804 FLAG_smi_only_arrays); |
| 1801 FastCloneShallowArrayStub::Mode mode = | 1805 FastCloneShallowArrayStub::Mode mode = |
| 1802 FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS; | 1806 FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS; |
| 1803 AllocationSiteMode allocation_site_mode = FLAG_track_allocation_sites | 1807 AllocationSiteMode allocation_site_mode = FLAG_track_allocation_sites |
| 1804 ? TRACK_ALLOCATION_SITE : DONT_TRACK_ALLOCATION_SITE; | 1808 ? TRACK_ALLOCATION_SITE : DONT_TRACK_ALLOCATION_SITE; |
| (...skipping 1651 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3456 | 3460 |
| 3457 __ Bind(&done); | 3461 __ Bind(&done); |
| 3458 context()->Plug(result); | 3462 context()->Plug(result); |
| 3459 } | 3463 } |
| 3460 | 3464 |
| 3461 | 3465 |
| 3462 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { | 3466 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { |
| 3463 ASM_LOCATION("FullCodeGenerator::EmitStringAdd"); | 3467 ASM_LOCATION("FullCodeGenerator::EmitStringAdd"); |
| 3464 ZoneList<Expression*>* args = expr->arguments(); | 3468 ZoneList<Expression*>* args = expr->arguments(); |
| 3465 ASSERT_EQ(2, args->length()); | 3469 ASSERT_EQ(2, args->length()); |
| 3466 VisitForStackValue(args->at(0)); | 3470 |
| 3467 VisitForStackValue(args->at(1)); | 3471 if (FLAG_new_string_add) { |
| 3472 VisitForStackValue(args->at(0)); |
| 3473 VisitForAccumulatorValue(args->at(1)); |
| 3474 |
| 3475 __ Pop(x1); |
| 3476 NewStringAddStub stub(STRING_ADD_CHECK_BOTH, NOT_TENURED); |
| 3477 __ CallStub(&stub); |
| 3478 } else { |
| 3479 VisitForStackValue(args->at(0)); |
| 3480 VisitForStackValue(args->at(1)); |
| 3481 } |
| 3468 | 3482 |
| 3469 StringAddStub stub(STRING_ADD_CHECK_BOTH); | 3483 StringAddStub stub(STRING_ADD_CHECK_BOTH); |
| 3470 __ CallStub(&stub); | 3484 __ CallStub(&stub); |
| 3471 context()->Plug(x0); | 3485 context()->Plug(x0); |
| 3472 } | 3486 } |
| 3473 | 3487 |
| 3474 | 3488 |
| 3475 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { | 3489 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { |
| 3476 ZoneList<Expression*>* args = expr->arguments(); | 3490 ZoneList<Expression*>* args = expr->arguments(); |
| 3477 ASSERT_EQ(2, args->length()); | 3491 ASSERT_EQ(2, args->length()); |
| (...skipping 658 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4136 } | 4150 } |
| 4137 | 4151 |
| 4138 // We need a second deoptimization point after loading the value | 4152 // We need a second deoptimization point after loading the value |
| 4139 // in case evaluating the property load my have a side effect. | 4153 // in case evaluating the property load my have a side effect. |
| 4140 if (assign_type == VARIABLE) { | 4154 if (assign_type == VARIABLE) { |
| 4141 PrepareForBailout(expr->expression(), TOS_REG); | 4155 PrepareForBailout(expr->expression(), TOS_REG); |
| 4142 } else { | 4156 } else { |
| 4143 PrepareForBailoutForId(prop->LoadId(), TOS_REG); | 4157 PrepareForBailoutForId(prop->LoadId(), TOS_REG); |
| 4144 } | 4158 } |
| 4145 | 4159 |
| 4146 // Call ToNumber only if operand is not a smi. | 4160 // Inline smi case if we are in a loop. |
| 4147 Label no_conversion; | 4161 Label stub_call, done; |
| 4162 JumpPatchSite patch_site(masm_); |
| 4163 |
| 4164 int count_value = expr->op() == Token::INC ? 1 : -1; |
| 4148 if (ShouldInlineSmiCase(expr->op())) { | 4165 if (ShouldInlineSmiCase(expr->op())) { |
| 4149 __ JumpIfSmi(x0, &no_conversion); | 4166 Label slow; |
| 4167 patch_site.EmitJumpIfNotSmi(x0, &slow); |
| 4168 |
| 4169 // Save result for postfix expressions. |
| 4170 if (expr->is_postfix()) { |
| 4171 if (!context()->IsEffect()) { |
| 4172 // Save the result on the stack. If we have a named or keyed property we |
| 4173 // store the result under the receiver that is currently on top of the |
| 4174 // stack. |
| 4175 switch (assign_type) { |
| 4176 case VARIABLE: |
| 4177 __ Push(x0); |
| 4178 break; |
| 4179 case NAMED_PROPERTY: |
| 4180 __ Poke(x0, kPointerSize); |
| 4181 break; |
| 4182 case KEYED_PROPERTY: |
| 4183 __ Poke(x0, kPointerSize * 2); |
| 4184 break; |
| 4185 } |
| 4186 } |
| 4187 } |
| 4188 |
| 4189 __ Adds(x0, x0, Operand(Smi::FromInt(count_value))); |
| 4190 __ B(vc, &done); |
| 4191 // Call stub. Undo operation first. |
| 4192 __ Sub(x0, x0, Operand(Smi::FromInt(count_value))); |
| 4193 __ B(&stub_call); |
| 4194 __ Bind(&slow); |
| 4150 } | 4195 } |
| 4151 ToNumberStub convert_stub; | 4196 ToNumberStub convert_stub; |
| 4152 __ CallStub(&convert_stub); | 4197 __ CallStub(&convert_stub); |
| 4153 __ Bind(&no_conversion); | |
| 4154 | 4198 |
| 4155 // Save result for postfix expressions. | 4199 // Save result for postfix expressions. |
| 4156 if (expr->is_postfix()) { | 4200 if (expr->is_postfix()) { |
| 4157 if (!context()->IsEffect()) { | 4201 if (!context()->IsEffect()) { |
| 4158 // Save the result on the stack. If we have a named or keyed property | 4202 // Save the result on the stack. If we have a named or keyed property |
| 4159 // we store the result under the receiver that is currently on top | 4203 // we store the result under the receiver that is currently on top |
| 4160 // of the stack. | 4204 // of the stack. |
| 4161 switch (assign_type) { | 4205 switch (assign_type) { |
| 4162 case VARIABLE: | 4206 case VARIABLE: |
| 4163 __ Push(x0); | 4207 __ Push(x0); |
| 4164 break; | 4208 break; |
| 4165 case NAMED_PROPERTY: | 4209 case NAMED_PROPERTY: |
| 4166 __ Poke(x0, kXRegSizeInBytes); | 4210 __ Poke(x0, kXRegSizeInBytes); |
| 4167 break; | 4211 break; |
| 4168 case KEYED_PROPERTY: | 4212 case KEYED_PROPERTY: |
| 4169 __ Poke(x0, 2 * kXRegSizeInBytes); | 4213 __ Poke(x0, 2 * kXRegSizeInBytes); |
| 4170 break; | 4214 break; |
| 4171 } | 4215 } |
| 4172 } | 4216 } |
| 4173 } | 4217 } |
| 4174 | 4218 |
| 4175 | 4219 __ Bind(&stub_call); |
| 4176 // Inline smi case if we are in a loop. | |
| 4177 Label done; | |
| 4178 JumpPatchSite patch_site(masm_); | |
| 4179 | |
| 4180 int count_value = expr->op() == Token::INC ? 1 : -1; | |
| 4181 if (ShouldInlineSmiCase(expr->op())) { | |
| 4182 Label stub_call; | |
| 4183 // Try the add using SMI operations. | |
| 4184 __ Adds(x0, x0, Operand(Smi::FromInt(count_value))); | |
| 4185 __ B(vs, &stub_call); | |
| 4186 // We could eliminate this smi check if we split the code at | |
| 4187 // the first smi check before calling ToNumber. | |
| 4188 patch_site.EmitJumpIfSmi(x0, &done); | |
| 4189 | |
| 4190 // Reverse the speculative add, then fall back to a stub call. | |
| 4191 __ Bind(&stub_call); | |
| 4192 __ Sub(x0, x0, Operand(Smi::FromInt(count_value))); | |
| 4193 } | |
| 4194 __ Mov(x1, x0); | 4220 __ Mov(x1, x0); |
| 4195 __ Mov(x0, Operand(Smi::FromInt(count_value))); | 4221 __ Mov(x0, Operand(Smi::FromInt(count_value))); |
| 4196 | 4222 |
| 4197 // Record position before stub call. | 4223 // Record position before stub call. |
| 4198 SetSourcePosition(expr->position()); | 4224 SetSourcePosition(expr->position()); |
| 4199 | 4225 |
| 4200 { | 4226 { |
| 4201 Assembler::BlockConstPoolScope scope(masm_); | 4227 Assembler::BlockConstPoolScope scope(masm_); |
| 4202 BinaryOpStub stub(Token::ADD, NO_OVERWRITE); | 4228 BinaryOpStub stub(Token::ADD, NO_OVERWRITE); |
| 4203 CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, | 4229 CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, |
| (...skipping 858 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5062 return previous_; | 5088 return previous_; |
| 5063 } | 5089 } |
| 5064 | 5090 |
| 5065 | 5091 |
| 5066 #undef __ | 5092 #undef __ |
| 5067 | 5093 |
| 5068 | 5094 |
| 5069 } } // namespace v8::internal | 5095 } } // namespace v8::internal |
| 5070 | 5096 |
| 5071 #endif // V8_TARGET_ARCH_A64 | 5097 #endif // V8_TARGET_ARCH_A64 |
| OLD | NEW |