| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 555 if (true_label_ != fall_through_) __ b(true_label_); | 555 if (true_label_ != fall_through_) __ b(true_label_); |
| 556 } else { | 556 } else { |
| 557 if (false_label_ != fall_through_) __ b(false_label_); | 557 if (false_label_ != fall_through_) __ b(false_label_); |
| 558 } | 558 } |
| 559 } | 559 } |
| 560 | 560 |
| 561 | 561 |
| 562 void FullCodeGenerator::DoTest(Label* if_true, | 562 void FullCodeGenerator::DoTest(Label* if_true, |
| 563 Label* if_false, | 563 Label* if_false, |
| 564 Label* fall_through) { | 564 Label* fall_through) { |
| 565 if (CpuFeatures::IsSupported(VFP3)) { | 565 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 566 CpuFeatures::Scope scope(VFP3); | 566 CpuFeatures::Scope scope(VFP3); |
| 567 // Emit the inlined tests assumed by the stub. | 567 // Emit the inlined tests assumed by the stub. |
| 568 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 568 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 569 __ cmp(result_register(), ip); | 569 __ cmp(result_register(), ip); |
| 570 __ b(eq, if_false); | 570 __ b(eq, if_false); |
| 571 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 571 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
| 572 __ cmp(result_register(), ip); | 572 __ cmp(result_register(), ip); |
| 573 __ b(eq, if_true); | 573 __ b(eq, if_true); |
| 574 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | 574 __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
| 575 __ cmp(result_register(), ip); | 575 __ cmp(result_register(), ip); |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 774 VisitForAccumulatorValue(function); | 774 VisitForAccumulatorValue(function); |
| 775 __ pop(r2); | 775 __ pop(r2); |
| 776 } else { | 776 } else { |
| 777 __ mov(r2, r0); | 777 __ mov(r2, r0); |
| 778 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); | 778 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); |
| 779 } | 779 } |
| 780 ASSERT(prop->key()->AsLiteral() != NULL && | 780 ASSERT(prop->key()->AsLiteral() != NULL && |
| 781 prop->key()->AsLiteral()->handle()->IsSmi()); | 781 prop->key()->AsLiteral()->handle()->IsSmi()); |
| 782 __ mov(r1, Operand(prop->key()->AsLiteral()->handle())); | 782 __ mov(r1, Operand(prop->key()->AsLiteral()->handle())); |
| 783 | 783 |
| 784 Handle<Code> ic(Builtins::builtin( | 784 Handle<Code> ic(isolate()->builtins()->builtin(is_strict_mode() |
| 785 is_strict_mode() ? Builtins::KeyedStoreIC_Initialize_Strict | 785 ? Builtins::KeyedStoreIC_Initialize_Strict |
| 786 : Builtins::KeyedStoreIC_Initialize)); | 786 : Builtins::KeyedStoreIC_Initialize)); |
| 787 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 787 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 788 // Value in r0 is ignored (declarations are statements). | 788 // Value in r0 is ignored (declarations are statements). |
| 789 } | 789 } |
| 790 } | 790 } |
| 791 } | 791 } |
| 792 | 792 |
| 793 | 793 |
| 794 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { | 794 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { |
| 795 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); | 795 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); |
| 796 } | 796 } |
| (...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1179 key_literal != NULL && | 1179 key_literal != NULL && |
| 1180 obj_proxy->IsArguments() && | 1180 obj_proxy->IsArguments() && |
| 1181 key_literal->handle()->IsSmi()) { | 1181 key_literal->handle()->IsSmi()) { |
| 1182 // Load arguments object if there are no eval-introduced | 1182 // Load arguments object if there are no eval-introduced |
| 1183 // variables. Then load the argument from the arguments | 1183 // variables. Then load the argument from the arguments |
| 1184 // object using keyed load. | 1184 // object using keyed load. |
| 1185 __ ldr(r1, | 1185 __ ldr(r1, |
| 1186 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), | 1186 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), |
| 1187 slow)); | 1187 slow)); |
| 1188 __ mov(r0, Operand(key_literal->handle())); | 1188 __ mov(r0, Operand(key_literal->handle())); |
| 1189 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1189 Handle<Code> ic(isolate()->builtins()->builtin( |
| 1190 Builtins::KeyedLoadIC_Initialize)); |
| 1190 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1191 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 1191 __ jmp(done); | 1192 __ jmp(done); |
| 1192 } | 1193 } |
| 1193 } | 1194 } |
| 1194 } | 1195 } |
| 1195 } | 1196 } |
| 1196 } | 1197 } |
| 1197 | 1198 |
| 1198 | 1199 |
| 1199 void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( | 1200 void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1245 __ ldr(next, FieldMemOperand(next, JSFunction::kContextOffset)); | 1246 __ ldr(next, FieldMemOperand(next, JSFunction::kContextOffset)); |
| 1246 __ b(&loop); | 1247 __ b(&loop); |
| 1247 __ bind(&fast); | 1248 __ bind(&fast); |
| 1248 } | 1249 } |
| 1249 | 1250 |
| 1250 __ ldr(r0, GlobalObjectOperand()); | 1251 __ ldr(r0, GlobalObjectOperand()); |
| 1251 __ mov(r2, Operand(slot->var()->name())); | 1252 __ mov(r2, Operand(slot->var()->name())); |
| 1252 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) | 1253 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) |
| 1253 ? RelocInfo::CODE_TARGET | 1254 ? RelocInfo::CODE_TARGET |
| 1254 : RelocInfo::CODE_TARGET_CONTEXT; | 1255 : RelocInfo::CODE_TARGET_CONTEXT; |
| 1255 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1256 Handle<Code> ic(isolate()->builtins()->builtin( |
| 1257 Builtins::LoadIC_Initialize)); |
| 1256 EmitCallIC(ic, mode); | 1258 EmitCallIC(ic, mode); |
| 1257 } | 1259 } |
| 1258 | 1260 |
| 1259 | 1261 |
| 1260 void FullCodeGenerator::EmitVariableLoad(Variable* var) { | 1262 void FullCodeGenerator::EmitVariableLoad(Variable* var) { |
| 1261 // Four cases: non-this global variables, lookup slots, all other | 1263 // Four cases: non-this global variables, lookup slots, all other |
| 1262 // types of slots, and parameters that rewrite to explicit property | 1264 // types of slots, and parameters that rewrite to explicit property |
| 1263 // accesses on the arguments object. | 1265 // accesses on the arguments object. |
| 1264 Slot* slot = var->AsSlot(); | 1266 Slot* slot = var->AsSlot(); |
| 1265 Property* property = var->AsProperty(); | 1267 Property* property = var->AsProperty(); |
| 1266 | 1268 |
| 1267 if (var->is_global() && !var->is_this()) { | 1269 if (var->is_global() && !var->is_this()) { |
| 1268 Comment cmnt(masm_, "Global variable"); | 1270 Comment cmnt(masm_, "Global variable"); |
| 1269 // Use inline caching. Variable name is passed in r2 and the global | 1271 // Use inline caching. Variable name is passed in r2 and the global |
| 1270 // object (receiver) in r0. | 1272 // object (receiver) in r0. |
| 1271 __ ldr(r0, GlobalObjectOperand()); | 1273 __ ldr(r0, GlobalObjectOperand()); |
| 1272 __ mov(r2, Operand(var->name())); | 1274 __ mov(r2, Operand(var->name())); |
| 1273 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1275 Handle<Code> ic(isolate()->builtins()->builtin( |
| 1276 Builtins::LoadIC_Initialize)); |
| 1274 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1277 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); |
| 1275 context()->Plug(r0); | 1278 context()->Plug(r0); |
| 1276 | 1279 |
| 1277 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { | 1280 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { |
| 1278 Label done, slow; | 1281 Label done, slow; |
| 1279 | 1282 |
| 1280 // Generate code for loading from variables potentially shadowed | 1283 // Generate code for loading from variables potentially shadowed |
| 1281 // by eval-introduced variables. | 1284 // by eval-introduced variables. |
| 1282 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); | 1285 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); |
| 1283 | 1286 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1322 | 1325 |
| 1323 // Assert that the key is a smi. | 1326 // Assert that the key is a smi. |
| 1324 Literal* key_literal = property->key()->AsLiteral(); | 1327 Literal* key_literal = property->key()->AsLiteral(); |
| 1325 ASSERT_NOT_NULL(key_literal); | 1328 ASSERT_NOT_NULL(key_literal); |
| 1326 ASSERT(key_literal->handle()->IsSmi()); | 1329 ASSERT(key_literal->handle()->IsSmi()); |
| 1327 | 1330 |
| 1328 // Load the key. | 1331 // Load the key. |
| 1329 __ mov(r0, Operand(key_literal->handle())); | 1332 __ mov(r0, Operand(key_literal->handle())); |
| 1330 | 1333 |
| 1331 // Call keyed load IC. It has arguments key and receiver in r0 and r1. | 1334 // Call keyed load IC. It has arguments key and receiver in r0 and r1. |
| 1332 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1335 Handle<Code> ic(isolate()->builtins()->builtin( |
| 1336 Builtins::KeyedLoadIC_Initialize)); |
| 1333 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1337 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 1334 context()->Plug(r0); | 1338 context()->Plug(r0); |
| 1335 } | 1339 } |
| 1336 } | 1340 } |
| 1337 | 1341 |
| 1338 | 1342 |
| 1339 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1343 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 1340 Comment cmnt(masm_, "[ RegExpLiteral"); | 1344 Comment cmnt(masm_, "[ RegExpLiteral"); |
| 1341 Label materialized; | 1345 Label materialized; |
| 1342 // Registers will be used as follows: | 1346 // Registers will be used as follows: |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1425 UNREACHABLE(); | 1429 UNREACHABLE(); |
| 1426 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1430 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1427 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); | 1431 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); |
| 1428 // Fall through. | 1432 // Fall through. |
| 1429 case ObjectLiteral::Property::COMPUTED: | 1433 case ObjectLiteral::Property::COMPUTED: |
| 1430 if (key->handle()->IsSymbol()) { | 1434 if (key->handle()->IsSymbol()) { |
| 1431 if (property->emit_store()) { | 1435 if (property->emit_store()) { |
| 1432 VisitForAccumulatorValue(value); | 1436 VisitForAccumulatorValue(value); |
| 1433 __ mov(r2, Operand(key->handle())); | 1437 __ mov(r2, Operand(key->handle())); |
| 1434 __ ldr(r1, MemOperand(sp)); | 1438 __ ldr(r1, MemOperand(sp)); |
| 1435 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1439 Handle<Code> ic(isolate()->builtins()->builtin( |
| 1440 Builtins::StoreIC_Initialize)); |
| 1436 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1441 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 1437 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1442 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
| 1438 } else { | 1443 } else { |
| 1439 VisitForEffect(value); | 1444 VisitForEffect(value); |
| 1440 } | 1445 } |
| 1441 break; | 1446 break; |
| 1442 } | 1447 } |
| 1443 // Fall through. | 1448 // Fall through. |
| 1444 case ObjectLiteral::Property::PROTOTYPE: | 1449 case ObjectLiteral::Property::PROTOTYPE: |
| 1445 // Duplicate receiver on stack. | 1450 // Duplicate receiver on stack. |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1483 Comment cmnt(masm_, "[ ArrayLiteral"); | 1488 Comment cmnt(masm_, "[ ArrayLiteral"); |
| 1484 | 1489 |
| 1485 ZoneList<Expression*>* subexprs = expr->values(); | 1490 ZoneList<Expression*>* subexprs = expr->values(); |
| 1486 int length = subexprs->length(); | 1491 int length = subexprs->length(); |
| 1487 | 1492 |
| 1488 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1493 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1489 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); | 1494 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); |
| 1490 __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); | 1495 __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); |
| 1491 __ mov(r1, Operand(expr->constant_elements())); | 1496 __ mov(r1, Operand(expr->constant_elements())); |
| 1492 __ Push(r3, r2, r1); | 1497 __ Push(r3, r2, r1); |
| 1493 if (expr->constant_elements()->map() == Heap::fixed_cow_array_map()) { | 1498 if (expr->constant_elements()->map() == |
| 1499 isolate()->heap()->fixed_cow_array_map()) { |
| 1494 FastCloneShallowArrayStub stub( | 1500 FastCloneShallowArrayStub stub( |
| 1495 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length); | 1501 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length); |
| 1496 __ CallStub(&stub); | 1502 __ CallStub(&stub); |
| 1497 __ IncrementCounter(&Counters::cow_arrays_created_stub, 1, r1, r2); | 1503 __ IncrementCounter( |
| 1504 isolate()->counters()->cow_arrays_created_stub(), 1, r1, r2); |
| 1498 } else if (expr->depth() > 1) { | 1505 } else if (expr->depth() > 1) { |
| 1499 __ CallRuntime(Runtime::kCreateArrayLiteral, 3); | 1506 __ CallRuntime(Runtime::kCreateArrayLiteral, 3); |
| 1500 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { | 1507 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { |
| 1501 __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); | 1508 __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); |
| 1502 } else { | 1509 } else { |
| 1503 FastCloneShallowArrayStub stub( | 1510 FastCloneShallowArrayStub stub( |
| 1504 FastCloneShallowArrayStub::CLONE_ELEMENTS, length); | 1511 FastCloneShallowArrayStub::CLONE_ELEMENTS, length); |
| 1505 __ CallStub(&stub); | 1512 __ CallStub(&stub); |
| 1506 } | 1513 } |
| 1507 | 1514 |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1671 break; | 1678 break; |
| 1672 } | 1679 } |
| 1673 } | 1680 } |
| 1674 | 1681 |
| 1675 | 1682 |
| 1676 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 1683 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
| 1677 SetSourcePosition(prop->position()); | 1684 SetSourcePosition(prop->position()); |
| 1678 Literal* key = prop->key()->AsLiteral(); | 1685 Literal* key = prop->key()->AsLiteral(); |
| 1679 __ mov(r2, Operand(key->handle())); | 1686 __ mov(r2, Operand(key->handle())); |
| 1680 // Call load IC. It has arguments receiver and property name r0 and r2. | 1687 // Call load IC. It has arguments receiver and property name r0 and r2. |
| 1681 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1688 Handle<Code> ic(isolate()->builtins()->builtin( |
| 1689 Builtins::LoadIC_Initialize)); |
| 1682 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1690 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 1683 } | 1691 } |
| 1684 | 1692 |
| 1685 | 1693 |
| 1686 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1694 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
| 1687 SetSourcePosition(prop->position()); | 1695 SetSourcePosition(prop->position()); |
| 1688 // Call keyed load IC. It has arguments key and receiver in r0 and r1. | 1696 // Call keyed load IC. It has arguments key and receiver in r0 and r1. |
| 1689 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1697 Handle<Code> ic(isolate()->builtins()->builtin( |
| 1698 Builtins::KeyedLoadIC_Initialize)); |
| 1690 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1699 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 1691 } | 1700 } |
| 1692 | 1701 |
| 1693 | 1702 |
| 1694 void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr, | 1703 void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr, |
| 1695 Token::Value op, | 1704 Token::Value op, |
| 1696 OverwriteMode mode, | 1705 OverwriteMode mode, |
| 1697 Expression* left_expr, | 1706 Expression* left_expr, |
| 1698 Expression* right_expr) { | 1707 Expression* right_expr) { |
| 1699 Label done, smi_case, stub_call; | 1708 Label done, smi_case, stub_call; |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1824 EffectContext context(this); | 1833 EffectContext context(this); |
| 1825 EmitVariableAssignment(var, Token::ASSIGN); | 1834 EmitVariableAssignment(var, Token::ASSIGN); |
| 1826 break; | 1835 break; |
| 1827 } | 1836 } |
| 1828 case NAMED_PROPERTY: { | 1837 case NAMED_PROPERTY: { |
| 1829 __ push(r0); // Preserve value. | 1838 __ push(r0); // Preserve value. |
| 1830 VisitForAccumulatorValue(prop->obj()); | 1839 VisitForAccumulatorValue(prop->obj()); |
| 1831 __ mov(r1, r0); | 1840 __ mov(r1, r0); |
| 1832 __ pop(r0); // Restore value. | 1841 __ pop(r0); // Restore value. |
| 1833 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); | 1842 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); |
| 1834 Handle<Code> ic(Builtins::builtin( | 1843 Handle<Code> ic(isolate()->builtins()->builtin( |
| 1835 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict | 1844 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict |
| 1836 : Builtins::StoreIC_Initialize)); | 1845 : Builtins::StoreIC_Initialize)); |
| 1837 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1846 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 1838 break; | 1847 break; |
| 1839 } | 1848 } |
| 1840 case KEYED_PROPERTY: { | 1849 case KEYED_PROPERTY: { |
| 1841 __ push(r0); // Preserve value. | 1850 __ push(r0); // Preserve value. |
| 1842 if (prop->is_synthetic()) { | 1851 if (prop->is_synthetic()) { |
| 1843 ASSERT(prop->obj()->AsVariableProxy() != NULL); | 1852 ASSERT(prop->obj()->AsVariableProxy() != NULL); |
| 1844 ASSERT(prop->key()->AsLiteral() != NULL); | 1853 ASSERT(prop->key()->AsLiteral() != NULL); |
| 1845 { AccumulatorValueContext for_object(this); | 1854 { AccumulatorValueContext for_object(this); |
| 1846 EmitVariableLoad(prop->obj()->AsVariableProxy()->var()); | 1855 EmitVariableLoad(prop->obj()->AsVariableProxy()->var()); |
| 1847 } | 1856 } |
| 1848 __ mov(r2, r0); | 1857 __ mov(r2, r0); |
| 1849 __ mov(r1, Operand(prop->key()->AsLiteral()->handle())); | 1858 __ mov(r1, Operand(prop->key()->AsLiteral()->handle())); |
| 1850 } else { | 1859 } else { |
| 1851 VisitForStackValue(prop->obj()); | 1860 VisitForStackValue(prop->obj()); |
| 1852 VisitForAccumulatorValue(prop->key()); | 1861 VisitForAccumulatorValue(prop->key()); |
| 1853 __ mov(r1, r0); | 1862 __ mov(r1, r0); |
| 1854 __ pop(r2); | 1863 __ pop(r2); |
| 1855 } | 1864 } |
| 1856 __ pop(r0); // Restore value. | 1865 __ pop(r0); // Restore value. |
| 1857 Handle<Code> ic(Builtins::builtin( | 1866 Handle<Code> ic(isolate()->builtins()->builtin( |
| 1858 is_strict_mode() ? Builtins::KeyedStoreIC_Initialize_Strict | 1867 is_strict_mode() ? Builtins::KeyedStoreIC_Initialize_Strict |
| 1859 : Builtins::KeyedStoreIC_Initialize)); | 1868 : Builtins::KeyedStoreIC_Initialize)); |
| 1860 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1869 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 1861 break; | 1870 break; |
| 1862 } | 1871 } |
| 1863 } | 1872 } |
| 1864 PrepareForBailoutForId(bailout_ast_id, TOS_REG); | 1873 PrepareForBailoutForId(bailout_ast_id, TOS_REG); |
| 1865 context()->Plug(r0); | 1874 context()->Plug(r0); |
| 1866 } | 1875 } |
| 1867 | 1876 |
| 1868 | 1877 |
| 1869 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1878 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
| 1870 Token::Value op) { | 1879 Token::Value op) { |
| 1871 // Left-hand sides that rewrite to explicit property accesses do not reach | 1880 // Left-hand sides that rewrite to explicit property accesses do not reach |
| 1872 // here. | 1881 // here. |
| 1873 ASSERT(var != NULL); | 1882 ASSERT(var != NULL); |
| 1874 ASSERT(var->is_global() || var->AsSlot() != NULL); | 1883 ASSERT(var->is_global() || var->AsSlot() != NULL); |
| 1875 | 1884 |
| 1876 if (var->is_global()) { | 1885 if (var->is_global()) { |
| 1877 ASSERT(!var->is_this()); | 1886 ASSERT(!var->is_this()); |
| 1878 // Assignment to a global variable. Use inline caching for the | 1887 // Assignment to a global variable. Use inline caching for the |
| 1879 // assignment. Right-hand-side value is passed in r0, variable name in | 1888 // assignment. Right-hand-side value is passed in r0, variable name in |
| 1880 // r2, and the global object in r1. | 1889 // r2, and the global object in r1. |
| 1881 __ mov(r2, Operand(var->name())); | 1890 __ mov(r2, Operand(var->name())); |
| 1882 __ ldr(r1, GlobalObjectOperand()); | 1891 __ ldr(r1, GlobalObjectOperand()); |
| 1883 Handle<Code> ic(Builtins::builtin( | 1892 Handle<Code> ic(isolate()->builtins()->builtin( |
| 1884 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict | 1893 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict |
| 1885 : Builtins::StoreIC_Initialize)); | 1894 : Builtins::StoreIC_Initialize)); |
| 1886 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1895 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); |
| 1887 | 1896 |
| 1888 } else if (op == Token::INIT_CONST) { | 1897 } else if (op == Token::INIT_CONST) { |
| 1889 // Like var declarations, const declarations are hoisted to function | 1898 // Like var declarations, const declarations are hoisted to function |
| 1890 // scope. However, unlike var initializers, const initializers are able | 1899 // scope. However, unlike var initializers, const initializers are able |
| 1891 // to drill a hole to that function context, even from inside a 'with' | 1900 // to drill a hole to that function context, even from inside a 'with' |
| 1892 // context. We thus bypass the normal static scope lookup. | 1901 // context. We thus bypass the normal static scope lookup. |
| 1893 Slot* slot = var->AsSlot(); | 1902 Slot* slot = var->AsSlot(); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1982 SetSourcePosition(expr->position()); | 1991 SetSourcePosition(expr->position()); |
| 1983 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); | 1992 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); |
| 1984 // Load receiver to r1. Leave a copy in the stack if needed for turning the | 1993 // Load receiver to r1. Leave a copy in the stack if needed for turning the |
| 1985 // receiver into fast case. | 1994 // receiver into fast case. |
| 1986 if (expr->ends_initialization_block()) { | 1995 if (expr->ends_initialization_block()) { |
| 1987 __ ldr(r1, MemOperand(sp)); | 1996 __ ldr(r1, MemOperand(sp)); |
| 1988 } else { | 1997 } else { |
| 1989 __ pop(r1); | 1998 __ pop(r1); |
| 1990 } | 1999 } |
| 1991 | 2000 |
| 1992 Handle<Code> ic(Builtins::builtin( | 2001 Handle<Code> ic(isolate()->builtins()->builtin( |
| 1993 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict | 2002 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict |
| 1994 : Builtins::StoreIC_Initialize)); | 2003 : Builtins::StoreIC_Initialize)); |
| 1995 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 2004 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 1996 | 2005 |
| 1997 // If the assignment ends an initialization block, revert to fast case. | 2006 // If the assignment ends an initialization block, revert to fast case. |
| 1998 if (expr->ends_initialization_block()) { | 2007 if (expr->ends_initialization_block()) { |
| 1999 __ push(r0); // Result of assignment, saved even if not needed. | 2008 __ push(r0); // Result of assignment, saved even if not needed. |
| 2000 // Receiver is under the result value. | 2009 // Receiver is under the result value. |
| 2001 __ ldr(ip, MemOperand(sp, kPointerSize)); | 2010 __ ldr(ip, MemOperand(sp, kPointerSize)); |
| 2002 __ push(ip); | 2011 __ push(ip); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2028 SetSourcePosition(expr->position()); | 2037 SetSourcePosition(expr->position()); |
| 2029 __ pop(r1); // Key. | 2038 __ pop(r1); // Key. |
| 2030 // Load receiver to r2. Leave a copy in the stack if needed for turning the | 2039 // Load receiver to r2. Leave a copy in the stack if needed for turning the |
| 2031 // receiver into fast case. | 2040 // receiver into fast case. |
| 2032 if (expr->ends_initialization_block()) { | 2041 if (expr->ends_initialization_block()) { |
| 2033 __ ldr(r2, MemOperand(sp)); | 2042 __ ldr(r2, MemOperand(sp)); |
| 2034 } else { | 2043 } else { |
| 2035 __ pop(r2); | 2044 __ pop(r2); |
| 2036 } | 2045 } |
| 2037 | 2046 |
| 2038 Handle<Code> ic(Builtins::builtin( | 2047 Handle<Code> ic(isolate()->builtins()->builtin( |
| 2039 is_strict_mode() ? Builtins::KeyedStoreIC_Initialize_Strict | 2048 is_strict_mode() ? Builtins::KeyedStoreIC_Initialize_Strict |
| 2040 : Builtins::KeyedStoreIC_Initialize)); | 2049 : Builtins::KeyedStoreIC_Initialize)); |
| 2041 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 2050 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 2042 | 2051 |
| 2043 // If the assignment ends an initialization block, revert to fast case. | 2052 // If the assignment ends an initialization block, revert to fast case. |
| 2044 if (expr->ends_initialization_block()) { | 2053 if (expr->ends_initialization_block()) { |
| 2045 __ push(r0); // Result of assignment, saved even if not needed. | 2054 __ push(r0); // Result of assignment, saved even if not needed. |
| 2046 // Receiver is under the result value. | 2055 // Receiver is under the result value. |
| 2047 __ ldr(ip, MemOperand(sp, kPointerSize)); | 2056 __ ldr(ip, MemOperand(sp, kPointerSize)); |
| 2048 __ push(ip); | 2057 __ push(ip); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2081 { PreservePositionScope scope(masm()->positions_recorder()); | 2090 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2082 for (int i = 0; i < arg_count; i++) { | 2091 for (int i = 0; i < arg_count; i++) { |
| 2083 VisitForStackValue(args->at(i)); | 2092 VisitForStackValue(args->at(i)); |
| 2084 } | 2093 } |
| 2085 __ mov(r2, Operand(name)); | 2094 __ mov(r2, Operand(name)); |
| 2086 } | 2095 } |
| 2087 // Record source position for debugger. | 2096 // Record source position for debugger. |
| 2088 SetSourcePosition(expr->position()); | 2097 SetSourcePosition(expr->position()); |
| 2089 // Call the IC initialization code. | 2098 // Call the IC initialization code. |
| 2090 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2099 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 2091 Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop); | 2100 Handle<Code> ic = |
| 2101 isolate()->stub_cache()->ComputeCallInitialize(arg_count, in_loop); |
| 2092 EmitCallIC(ic, mode); | 2102 EmitCallIC(ic, mode); |
| 2093 RecordJSReturnSite(expr); | 2103 RecordJSReturnSite(expr); |
| 2094 // Restore context register. | 2104 // Restore context register. |
| 2095 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2105 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2096 context()->Plug(r0); | 2106 context()->Plug(r0); |
| 2097 } | 2107 } |
| 2098 | 2108 |
| 2099 | 2109 |
| 2100 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2110 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
| 2101 Expression* key, | 2111 Expression* key, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2114 int arg_count = args->length(); | 2124 int arg_count = args->length(); |
| 2115 { PreservePositionScope scope(masm()->positions_recorder()); | 2125 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2116 for (int i = 0; i < arg_count; i++) { | 2126 for (int i = 0; i < arg_count; i++) { |
| 2117 VisitForStackValue(args->at(i)); | 2127 VisitForStackValue(args->at(i)); |
| 2118 } | 2128 } |
| 2119 } | 2129 } |
| 2120 // Record source position for debugger. | 2130 // Record source position for debugger. |
| 2121 SetSourcePosition(expr->position()); | 2131 SetSourcePosition(expr->position()); |
| 2122 // Call the IC initialization code. | 2132 // Call the IC initialization code. |
| 2123 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2133 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 2124 Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arg_count, in_loop); | 2134 Handle<Code> ic = |
| 2135 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count, in_loop); |
| 2125 __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. | 2136 __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. |
| 2126 EmitCallIC(ic, mode); | 2137 EmitCallIC(ic, mode); |
| 2127 RecordJSReturnSite(expr); | 2138 RecordJSReturnSite(expr); |
| 2128 // Restore context register. | 2139 // Restore context register. |
| 2129 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2140 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2130 context()->DropAndPlug(1, r0); // Drop the key still on the stack. | 2141 context()->DropAndPlug(1, r0); // Drop the key still on the stack. |
| 2131 } | 2142 } |
| 2132 | 2143 |
| 2133 | 2144 |
| 2134 void FullCodeGenerator::EmitCallWithStub(Call* expr) { | 2145 void FullCodeGenerator::EmitCallWithStub(Call* expr) { |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2313 MemOperand operand = EmitSlotSearch(slot, r1); | 2324 MemOperand operand = EmitSlotSearch(slot, r1); |
| 2314 __ ldr(r1, operand); | 2325 __ ldr(r1, operand); |
| 2315 | 2326 |
| 2316 ASSERT(prop->key()->AsLiteral() != NULL); | 2327 ASSERT(prop->key()->AsLiteral() != NULL); |
| 2317 ASSERT(prop->key()->AsLiteral()->handle()->IsSmi()); | 2328 ASSERT(prop->key()->AsLiteral()->handle()->IsSmi()); |
| 2318 __ mov(r0, Operand(prop->key()->AsLiteral()->handle())); | 2329 __ mov(r0, Operand(prop->key()->AsLiteral()->handle())); |
| 2319 | 2330 |
| 2320 // Record source code position for IC call. | 2331 // Record source code position for IC call. |
| 2321 SetSourcePosition(prop->position()); | 2332 SetSourcePosition(prop->position()); |
| 2322 | 2333 |
| 2323 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 2334 Handle<Code> ic(isolate()->builtins()->builtin( |
| 2335 Builtins::KeyedLoadIC_Initialize)); |
| 2324 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 2336 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 2325 __ ldr(r1, GlobalObjectOperand()); | 2337 __ ldr(r1, GlobalObjectOperand()); |
| 2326 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); | 2338 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); |
| 2327 __ Push(r0, r1); // Function, receiver. | 2339 __ Push(r0, r1); // Function, receiver. |
| 2328 EmitCallWithStub(expr); | 2340 EmitCallWithStub(expr); |
| 2329 } else { | 2341 } else { |
| 2330 { PreservePositionScope scope(masm()->positions_recorder()); | 2342 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2331 VisitForStackValue(prop->obj()); | 2343 VisitForStackValue(prop->obj()); |
| 2332 } | 2344 } |
| 2333 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); | 2345 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); |
| 2334 } | 2346 } |
| 2335 } | 2347 } |
| 2336 } else { | 2348 } else { |
| 2337 // Call to some other expression. If the expression is an anonymous | 2349 // Call to some other expression. If the expression is an anonymous |
| 2338 // function literal not called in a loop, mark it as one that should | 2350 // function literal not called in a loop, mark it as one that should |
| 2339 // also use the fast code generator. | 2351 // also use the fast code generator. |
| 2340 FunctionLiteral* lit = fun->AsFunctionLiteral(); | 2352 FunctionLiteral* lit = fun->AsFunctionLiteral(); |
| 2341 if (lit != NULL && | 2353 if (lit != NULL && |
| 2342 lit->name()->Equals(Heap::empty_string()) && | 2354 lit->name()->Equals(isolate()->heap()->empty_string()) && |
| 2343 loop_depth() == 0) { | 2355 loop_depth() == 0) { |
| 2344 lit->set_try_full_codegen(true); | 2356 lit->set_try_full_codegen(true); |
| 2345 } | 2357 } |
| 2346 | 2358 |
| 2347 { PreservePositionScope scope(masm()->positions_recorder()); | 2359 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2348 VisitForStackValue(fun); | 2360 VisitForStackValue(fun); |
| 2349 } | 2361 } |
| 2350 // Load global receiver object. | 2362 // Load global receiver object. |
| 2351 __ ldr(r1, GlobalObjectOperand()); | 2363 __ ldr(r1, GlobalObjectOperand()); |
| 2352 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); | 2364 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 2381 } | 2393 } |
| 2382 | 2394 |
| 2383 // Call the construct call builtin that handles allocation and | 2395 // Call the construct call builtin that handles allocation and |
| 2384 // constructor invocation. | 2396 // constructor invocation. |
| 2385 SetSourcePosition(expr->position()); | 2397 SetSourcePosition(expr->position()); |
| 2386 | 2398 |
| 2387 // Load function and argument count into r1 and r0. | 2399 // Load function and argument count into r1 and r0. |
| 2388 __ mov(r0, Operand(arg_count)); | 2400 __ mov(r0, Operand(arg_count)); |
| 2389 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); | 2401 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); |
| 2390 | 2402 |
| 2391 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); | 2403 Handle<Code> construct_builtin(isolate()->builtins()->builtin( |
| 2404 Builtins::JSConstructCall)); |
| 2392 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); | 2405 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); |
| 2393 context()->Plug(r0); | 2406 context()->Plug(r0); |
| 2394 } | 2407 } |
| 2395 | 2408 |
| 2396 | 2409 |
| 2397 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { | 2410 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { |
| 2398 ASSERT(args->length() == 1); | 2411 ASSERT(args->length() == 1); |
| 2399 | 2412 |
| 2400 VisitForAccumulatorValue(args->at(0)); | 2413 VisitForAccumulatorValue(args->at(0)); |
| 2401 | 2414 |
| (...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2776 __ bind(&slow_allocate_heapnumber); | 2789 __ bind(&slow_allocate_heapnumber); |
| 2777 // Allocate a heap number. | 2790 // Allocate a heap number. |
| 2778 __ CallRuntime(Runtime::kNumberAlloc, 0); | 2791 __ CallRuntime(Runtime::kNumberAlloc, 0); |
| 2779 __ mov(r4, Operand(r0)); | 2792 __ mov(r4, Operand(r0)); |
| 2780 | 2793 |
| 2781 __ bind(&heapnumber_allocated); | 2794 __ bind(&heapnumber_allocated); |
| 2782 | 2795 |
| 2783 // Convert 32 random bits in r0 to 0.(32 random bits) in a double | 2796 // Convert 32 random bits in r0 to 0.(32 random bits) in a double |
| 2784 // by computing: | 2797 // by computing: |
| 2785 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). | 2798 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). |
| 2786 if (CpuFeatures::IsSupported(VFP3)) { | 2799 if (isolate()->cpu_features()->IsSupported(VFP3)) { |
| 2787 __ PrepareCallCFunction(0, r1); | 2800 __ PrepareCallCFunction(0, r1); |
| 2788 __ CallCFunction(ExternalReference::random_uint32_function(), 0); | 2801 __ CallCFunction(ExternalReference::random_uint32_function(), 0); |
| 2789 | 2802 |
| 2790 CpuFeatures::Scope scope(VFP3); | 2803 CpuFeatures::Scope scope(VFP3); |
| 2791 // 0x41300000 is the top half of 1.0 x 2^20 as a double. | 2804 // 0x41300000 is the top half of 1.0 x 2^20 as a double. |
| 2792 // Create this constant using mov/orr to avoid PC relative load. | 2805 // Create this constant using mov/orr to avoid PC relative load. |
| 2793 __ mov(r1, Operand(0x41000000)); | 2806 __ mov(r1, Operand(0x41000000)); |
| 2794 __ orr(r1, r1, Operand(0x300000)); | 2807 __ orr(r1, r1, Operand(0x300000)); |
| 2795 // Move 0x41300000xxxxxxxx (x = random bits) to VFP. | 2808 // Move 0x41300000xxxxxxxx (x = random bits) to VFP. |
| 2796 __ vmov(d7, r0, r1); | 2809 __ vmov(d7, r0, r1); |
| (...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3197 } | 3210 } |
| 3198 | 3211 |
| 3199 | 3212 |
| 3200 void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) { | 3213 void FullCodeGenerator::EmitGetFromCache(ZoneList<Expression*>* args) { |
| 3201 ASSERT_EQ(2, args->length()); | 3214 ASSERT_EQ(2, args->length()); |
| 3202 | 3215 |
| 3203 ASSERT_NE(NULL, args->at(0)->AsLiteral()); | 3216 ASSERT_NE(NULL, args->at(0)->AsLiteral()); |
| 3204 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); | 3217 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); |
| 3205 | 3218 |
| 3206 Handle<FixedArray> jsfunction_result_caches( | 3219 Handle<FixedArray> jsfunction_result_caches( |
| 3207 Top::global_context()->jsfunction_result_caches()); | 3220 isolate()->global_context()->jsfunction_result_caches()); |
| 3208 if (jsfunction_result_caches->length() <= cache_id) { | 3221 if (jsfunction_result_caches->length() <= cache_id) { |
| 3209 __ Abort("Attempt to use undefined cache."); | 3222 __ Abort("Attempt to use undefined cache."); |
| 3210 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 3223 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
| 3211 context()->Plug(r0); | 3224 context()->Plug(r0); |
| 3212 return; | 3225 return; |
| 3213 } | 3226 } |
| 3214 | 3227 |
| 3215 VisitForAccumulatorValue(args->at(1)); | 3228 VisitForAccumulatorValue(args->at(1)); |
| 3216 | 3229 |
| 3217 Register key = r0; | 3230 Register key = r0; |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3576 | 3589 |
| 3577 // Push the arguments ("left-to-right"). | 3590 // Push the arguments ("left-to-right"). |
| 3578 int arg_count = args->length(); | 3591 int arg_count = args->length(); |
| 3579 for (int i = 0; i < arg_count; i++) { | 3592 for (int i = 0; i < arg_count; i++) { |
| 3580 VisitForStackValue(args->at(i)); | 3593 VisitForStackValue(args->at(i)); |
| 3581 } | 3594 } |
| 3582 | 3595 |
| 3583 if (expr->is_jsruntime()) { | 3596 if (expr->is_jsruntime()) { |
| 3584 // Call the JS runtime function. | 3597 // Call the JS runtime function. |
| 3585 __ mov(r2, Operand(expr->name())); | 3598 __ mov(r2, Operand(expr->name())); |
| 3586 Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, NOT_IN_LOOP); | 3599 Handle<Code> ic = |
| 3600 isolate()->stub_cache()->ComputeCallInitialize(arg_count, NOT_IN_LOOP); |
| 3587 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3601 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 3588 // Restore context register. | 3602 // Restore context register. |
| 3589 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3603 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 3590 } else { | 3604 } else { |
| 3591 // Call the C runtime function. | 3605 // Call the C runtime function. |
| 3592 __ CallRuntime(expr->function(), arg_count); | 3606 __ CallRuntime(expr->function(), arg_count); |
| 3593 } | 3607 } |
| 3594 context()->Plug(r0); | 3608 context()->Plug(r0); |
| 3595 } | 3609 } |
| 3596 | 3610 |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3880 } else { | 3894 } else { |
| 3881 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3895 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 3882 Token::ASSIGN); | 3896 Token::ASSIGN); |
| 3883 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3897 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 3884 context()->Plug(r0); | 3898 context()->Plug(r0); |
| 3885 } | 3899 } |
| 3886 break; | 3900 break; |
| 3887 case NAMED_PROPERTY: { | 3901 case NAMED_PROPERTY: { |
| 3888 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); | 3902 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); |
| 3889 __ pop(r1); | 3903 __ pop(r1); |
| 3890 Handle<Code> ic(Builtins::builtin( | 3904 Handle<Code> ic(isolate()->builtins()->builtin( |
| 3891 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict | 3905 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict |
| 3892 : Builtins::StoreIC_Initialize)); | 3906 : Builtins::StoreIC_Initialize)); |
| 3893 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3907 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 3894 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3908 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 3895 if (expr->is_postfix()) { | 3909 if (expr->is_postfix()) { |
| 3896 if (!context()->IsEffect()) { | 3910 if (!context()->IsEffect()) { |
| 3897 context()->PlugTOS(); | 3911 context()->PlugTOS(); |
| 3898 } | 3912 } |
| 3899 } else { | 3913 } else { |
| 3900 context()->Plug(r0); | 3914 context()->Plug(r0); |
| 3901 } | 3915 } |
| 3902 break; | 3916 break; |
| 3903 } | 3917 } |
| 3904 case KEYED_PROPERTY: { | 3918 case KEYED_PROPERTY: { |
| 3905 __ pop(r1); // Key. | 3919 __ pop(r1); // Key. |
| 3906 __ pop(r2); // Receiver. | 3920 __ pop(r2); // Receiver. |
| 3907 Handle<Code> ic(Builtins::builtin( | 3921 Handle<Code> ic(isolate()->builtins()->builtin( |
| 3908 is_strict_mode() ? Builtins::KeyedStoreIC_Initialize_Strict | 3922 is_strict_mode() ? Builtins::KeyedStoreIC_Initialize_Strict |
| 3909 : Builtins::KeyedStoreIC_Initialize)); | 3923 : Builtins::KeyedStoreIC_Initialize)); |
| 3910 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3924 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 3911 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3925 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 3912 if (expr->is_postfix()) { | 3926 if (expr->is_postfix()) { |
| 3913 if (!context()->IsEffect()) { | 3927 if (!context()->IsEffect()) { |
| 3914 context()->PlugTOS(); | 3928 context()->PlugTOS(); |
| 3915 } | 3929 } |
| 3916 } else { | 3930 } else { |
| 3917 context()->Plug(r0); | 3931 context()->Plug(r0); |
| 3918 } | 3932 } |
| 3919 break; | 3933 break; |
| 3920 } | 3934 } |
| 3921 } | 3935 } |
| 3922 } | 3936 } |
| 3923 | 3937 |
| 3924 | 3938 |
| 3925 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | 3939 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { |
| 3926 ASSERT(!context()->IsEffect()); | 3940 ASSERT(!context()->IsEffect()); |
| 3927 ASSERT(!context()->IsTest()); | 3941 ASSERT(!context()->IsTest()); |
| 3928 VariableProxy* proxy = expr->AsVariableProxy(); | 3942 VariableProxy* proxy = expr->AsVariableProxy(); |
| 3929 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { | 3943 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { |
| 3930 Comment cmnt(masm_, "Global variable"); | 3944 Comment cmnt(masm_, "Global variable"); |
| 3931 __ ldr(r0, GlobalObjectOperand()); | 3945 __ ldr(r0, GlobalObjectOperand()); |
| 3932 __ mov(r2, Operand(proxy->name())); | 3946 __ mov(r2, Operand(proxy->name())); |
| 3933 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 3947 Handle<Code> ic(isolate()->builtins()->builtin( |
| 3948 Builtins::LoadIC_Initialize)); |
| 3934 // Use a regular load, not a contextual load, to avoid a reference | 3949 // Use a regular load, not a contextual load, to avoid a reference |
| 3935 // error. | 3950 // error. |
| 3936 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3951 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 3937 PrepareForBailout(expr, TOS_REG); | 3952 PrepareForBailout(expr, TOS_REG); |
| 3938 context()->Plug(r0); | 3953 context()->Plug(r0); |
| 3939 } else if (proxy != NULL && | 3954 } else if (proxy != NULL && |
| 3940 proxy->var()->AsSlot() != NULL && | 3955 proxy->var()->AsSlot() != NULL && |
| 3941 proxy->var()->AsSlot()->type() == Slot::LOOKUP) { | 3956 proxy->var()->AsSlot()->type() == Slot::LOOKUP) { |
| 3942 Label done, slow; | 3957 Label done, slow; |
| 3943 | 3958 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3976 if (!right_literal_value->IsString()) return false; | 3991 if (!right_literal_value->IsString()) return false; |
| 3977 UnaryOperation* left_unary = left->AsUnaryOperation(); | 3992 UnaryOperation* left_unary = left->AsUnaryOperation(); |
| 3978 if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false; | 3993 if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false; |
| 3979 Handle<String> check = Handle<String>::cast(right_literal_value); | 3994 Handle<String> check = Handle<String>::cast(right_literal_value); |
| 3980 | 3995 |
| 3981 { AccumulatorValueContext context(this); | 3996 { AccumulatorValueContext context(this); |
| 3982 VisitForTypeofValue(left_unary->expression()); | 3997 VisitForTypeofValue(left_unary->expression()); |
| 3983 } | 3998 } |
| 3984 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 3999 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
| 3985 | 4000 |
| 3986 if (check->Equals(Heap::number_symbol())) { | 4001 if (check->Equals(isolate()->heap()->number_symbol())) { |
| 3987 __ JumpIfSmi(r0, if_true); | 4002 __ JumpIfSmi(r0, if_true); |
| 3988 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); | 4003 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 3989 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 4004 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
| 3990 __ cmp(r0, ip); | 4005 __ cmp(r0, ip); |
| 3991 Split(eq, if_true, if_false, fall_through); | 4006 Split(eq, if_true, if_false, fall_through); |
| 3992 } else if (check->Equals(Heap::string_symbol())) { | 4007 } else if (check->Equals(isolate()->heap()->string_symbol())) { |
| 3993 __ JumpIfSmi(r0, if_false); | 4008 __ JumpIfSmi(r0, if_false); |
| 3994 // Check for undetectable objects => false. | 4009 // Check for undetectable objects => false. |
| 3995 __ CompareObjectType(r0, r0, r1, FIRST_NONSTRING_TYPE); | 4010 __ CompareObjectType(r0, r0, r1, FIRST_NONSTRING_TYPE); |
| 3996 __ b(ge, if_false); | 4011 __ b(ge, if_false); |
| 3997 __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); | 4012 __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); |
| 3998 __ tst(r1, Operand(1 << Map::kIsUndetectable)); | 4013 __ tst(r1, Operand(1 << Map::kIsUndetectable)); |
| 3999 Split(eq, if_true, if_false, fall_through); | 4014 Split(eq, if_true, if_false, fall_through); |
| 4000 } else if (check->Equals(Heap::boolean_symbol())) { | 4015 } else if (check->Equals(isolate()->heap()->boolean_symbol())) { |
| 4001 __ CompareRoot(r0, Heap::kTrueValueRootIndex); | 4016 __ CompareRoot(r0, Heap::kTrueValueRootIndex); |
| 4002 __ b(eq, if_true); | 4017 __ b(eq, if_true); |
| 4003 __ CompareRoot(r0, Heap::kFalseValueRootIndex); | 4018 __ CompareRoot(r0, Heap::kFalseValueRootIndex); |
| 4004 Split(eq, if_true, if_false, fall_through); | 4019 Split(eq, if_true, if_false, fall_through); |
| 4005 } else if (check->Equals(Heap::undefined_symbol())) { | 4020 } else if (check->Equals(isolate()->heap()->undefined_symbol())) { |
| 4006 __ CompareRoot(r0, Heap::kUndefinedValueRootIndex); | 4021 __ CompareRoot(r0, Heap::kUndefinedValueRootIndex); |
| 4007 __ b(eq, if_true); | 4022 __ b(eq, if_true); |
| 4008 __ JumpIfSmi(r0, if_false); | 4023 __ JumpIfSmi(r0, if_false); |
| 4009 // Check for undetectable objects => true. | 4024 // Check for undetectable objects => true. |
| 4010 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); | 4025 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 4011 __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); | 4026 __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); |
| 4012 __ tst(r1, Operand(1 << Map::kIsUndetectable)); | 4027 __ tst(r1, Operand(1 << Map::kIsUndetectable)); |
| 4013 Split(ne, if_true, if_false, fall_through); | 4028 Split(ne, if_true, if_false, fall_through); |
| 4014 | 4029 |
| 4015 } else if (check->Equals(Heap::function_symbol())) { | 4030 } else if (check->Equals(isolate()->heap()->function_symbol())) { |
| 4016 __ JumpIfSmi(r0, if_false); | 4031 __ JumpIfSmi(r0, if_false); |
| 4017 __ CompareObjectType(r0, r1, r0, FIRST_FUNCTION_CLASS_TYPE); | 4032 __ CompareObjectType(r0, r1, r0, FIRST_FUNCTION_CLASS_TYPE); |
| 4018 Split(ge, if_true, if_false, fall_through); | 4033 Split(ge, if_true, if_false, fall_through); |
| 4019 | 4034 |
| 4020 } else if (check->Equals(Heap::object_symbol())) { | 4035 } else if (check->Equals(isolate()->heap()->object_symbol())) { |
| 4021 __ JumpIfSmi(r0, if_false); | 4036 __ JumpIfSmi(r0, if_false); |
| 4022 __ CompareRoot(r0, Heap::kNullValueRootIndex); | 4037 __ CompareRoot(r0, Heap::kNullValueRootIndex); |
| 4023 __ b(eq, if_true); | 4038 __ b(eq, if_true); |
| 4024 // Check for JS objects => true. | 4039 // Check for JS objects => true. |
| 4025 __ CompareObjectType(r0, r0, r1, FIRST_JS_OBJECT_TYPE); | 4040 __ CompareObjectType(r0, r0, r1, FIRST_JS_OBJECT_TYPE); |
| 4026 __ b(lo, if_false); | 4041 __ b(lo, if_false); |
| 4027 __ CompareInstanceType(r0, r1, FIRST_FUNCTION_CLASS_TYPE); | 4042 __ CompareInstanceType(r0, r1, FIRST_FUNCTION_CLASS_TYPE); |
| 4028 __ b(hs, if_false); | 4043 __ b(hs, if_false); |
| 4029 // Check for undetectable objects => false. | 4044 // Check for undetectable objects => false. |
| 4030 __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); | 4045 __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4196 Register FullCodeGenerator::context_register() { | 4211 Register FullCodeGenerator::context_register() { |
| 4197 return cp; | 4212 return cp; |
| 4198 } | 4213 } |
| 4199 | 4214 |
| 4200 | 4215 |
| 4201 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) { | 4216 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) { |
| 4202 ASSERT(mode == RelocInfo::CODE_TARGET || | 4217 ASSERT(mode == RelocInfo::CODE_TARGET || |
| 4203 mode == RelocInfo::CODE_TARGET_CONTEXT); | 4218 mode == RelocInfo::CODE_TARGET_CONTEXT); |
| 4204 switch (ic->kind()) { | 4219 switch (ic->kind()) { |
| 4205 case Code::LOAD_IC: | 4220 case Code::LOAD_IC: |
| 4206 __ IncrementCounter(&Counters::named_load_full, 1, r1, r2); | 4221 __ IncrementCounter(COUNTERS->named_load_full(), 1, r1, r2); |
| 4207 break; | 4222 break; |
| 4208 case Code::KEYED_LOAD_IC: | 4223 case Code::KEYED_LOAD_IC: |
| 4209 __ IncrementCounter(&Counters::keyed_load_full, 1, r1, r2); | 4224 __ IncrementCounter(COUNTERS->keyed_load_full(), 1, r1, r2); |
| 4210 break; | 4225 break; |
| 4211 case Code::STORE_IC: | 4226 case Code::STORE_IC: |
| 4212 __ IncrementCounter(&Counters::named_store_full, 1, r1, r2); | 4227 __ IncrementCounter(COUNTERS->named_store_full(), 1, r1, r2); |
| 4213 break; | 4228 break; |
| 4214 case Code::KEYED_STORE_IC: | 4229 case Code::KEYED_STORE_IC: |
| 4215 __ IncrementCounter(&Counters::keyed_store_full, 1, r1, r2); | 4230 __ IncrementCounter(COUNTERS->keyed_store_full(), 1, r1, r2); |
| 4216 default: | 4231 default: |
| 4217 break; | 4232 break; |
| 4218 } | 4233 } |
| 4219 | 4234 |
| 4220 __ Call(ic, mode); | 4235 __ Call(ic, mode); |
| 4221 } | 4236 } |
| 4222 | 4237 |
| 4223 | 4238 |
| 4224 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) { | 4239 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) { |
| 4225 switch (ic->kind()) { | 4240 switch (ic->kind()) { |
| 4226 case Code::LOAD_IC: | 4241 case Code::LOAD_IC: |
| 4227 __ IncrementCounter(&Counters::named_load_full, 1, r1, r2); | 4242 __ IncrementCounter(COUNTERS->named_load_full(), 1, r1, r2); |
| 4228 break; | 4243 break; |
| 4229 case Code::KEYED_LOAD_IC: | 4244 case Code::KEYED_LOAD_IC: |
| 4230 __ IncrementCounter(&Counters::keyed_load_full, 1, r1, r2); | 4245 __ IncrementCounter(COUNTERS->keyed_load_full(), 1, r1, r2); |
| 4231 break; | 4246 break; |
| 4232 case Code::STORE_IC: | 4247 case Code::STORE_IC: |
| 4233 __ IncrementCounter(&Counters::named_store_full, 1, r1, r2); | 4248 __ IncrementCounter(COUNTERS->named_store_full(), 1, r1, r2); |
| 4234 break; | 4249 break; |
| 4235 case Code::KEYED_STORE_IC: | 4250 case Code::KEYED_STORE_IC: |
| 4236 __ IncrementCounter(&Counters::keyed_store_full, 1, r1, r2); | 4251 __ IncrementCounter(COUNTERS->keyed_store_full(), 1, r1, r2); |
| 4237 default: | 4252 default: |
| 4238 break; | 4253 break; |
| 4239 } | 4254 } |
| 4240 | 4255 |
| 4241 __ Call(ic, RelocInfo::CODE_TARGET); | 4256 __ Call(ic, RelocInfo::CODE_TARGET); |
| 4242 if (patch_site != NULL && patch_site->is_bound()) { | 4257 if (patch_site != NULL && patch_site->is_bound()) { |
| 4243 patch_site->EmitPatchInfo(); | 4258 patch_site->EmitPatchInfo(); |
| 4244 } else { | 4259 } else { |
| 4245 __ nop(); // Signals no inlined code. | 4260 __ nop(); // Signals no inlined code. |
| 4246 } | 4261 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4284 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 4299 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
| 4285 __ add(pc, r1, Operand(masm_->CodeObject())); | 4300 __ add(pc, r1, Operand(masm_->CodeObject())); |
| 4286 } | 4301 } |
| 4287 | 4302 |
| 4288 | 4303 |
| 4289 #undef __ | 4304 #undef __ |
| 4290 | 4305 |
| 4291 } } // namespace v8::internal | 4306 } } // namespace v8::internal |
| 4292 | 4307 |
| 4293 #endif // V8_TARGET_ARCH_ARM | 4308 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |