OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM | 7 #if V8_TARGET_ARCH_ARM |
8 | 8 |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 | 190 |
191 // Possibly allocate a local context. | 191 // Possibly allocate a local context. |
192 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 192 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
193 if (heap_slots > 0) { | 193 if (heap_slots > 0) { |
194 // Argument to NewContext is the function, which is still in r1. | 194 // Argument to NewContext is the function, which is still in r1. |
195 Comment cmnt(masm_, "[ Allocate context"); | 195 Comment cmnt(masm_, "[ Allocate context"); |
196 bool need_write_barrier = true; | 196 bool need_write_barrier = true; |
197 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) { | 197 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) { |
198 __ push(r1); | 198 __ push(r1); |
199 __ Push(info->scope()->GetScopeInfo()); | 199 __ Push(info->scope()->GetScopeInfo()); |
200 __ CallRuntime(Runtime::kHiddenNewGlobalContext, 2); | 200 __ CallRuntime(Runtime::kNewGlobalContext, 2); |
201 } else if (heap_slots <= FastNewContextStub::kMaximumSlots) { | 201 } else if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
202 FastNewContextStub stub(isolate(), heap_slots); | 202 FastNewContextStub stub(isolate(), heap_slots); |
203 __ CallStub(&stub); | 203 __ CallStub(&stub); |
204 // Result of FastNewContextStub is always in new space. | 204 // Result of FastNewContextStub is always in new space. |
205 need_write_barrier = false; | 205 need_write_barrier = false; |
206 } else { | 206 } else { |
207 __ push(r1); | 207 __ push(r1); |
208 __ CallRuntime(Runtime::kHiddenNewFunctionContext, 1); | 208 __ CallRuntime(Runtime::kNewFunctionContext, 1); |
209 } | 209 } |
210 function_in_register = false; | 210 function_in_register = false; |
211 // Context is returned in r0. It replaces the context passed to us. | 211 // Context is returned in r0. It replaces the context passed to us. |
212 // It's saved in the stack and kept live in cp. | 212 // It's saved in the stack and kept live in cp. |
213 __ mov(cp, r0); | 213 __ mov(cp, r0); |
214 __ str(r0, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 214 __ str(r0, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
215 // Copy any necessary parameters into the context. | 215 // Copy any necessary parameters into the context. |
216 int num_parameters = info->scope()->num_parameters(); | 216 int num_parameters = info->scope()->num_parameters(); |
217 for (int i = 0; i < num_parameters; i++) { | 217 for (int i = 0; i < num_parameters; i++) { |
218 Variable* var = scope()->parameter(i); | 218 Variable* var = scope()->parameter(i); |
(...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
834 // Note: For variables we must not push an initial value (such as | 834 // Note: For variables we must not push an initial value (such as |
835 // 'undefined') because we may have a (legal) redeclaration and we | 835 // 'undefined') because we may have a (legal) redeclaration and we |
836 // must not destroy the current value. | 836 // must not destroy the current value. |
837 if (hole_init) { | 837 if (hole_init) { |
838 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); | 838 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); |
839 __ Push(cp, r2, r1, r0); | 839 __ Push(cp, r2, r1, r0); |
840 } else { | 840 } else { |
841 __ mov(r0, Operand(Smi::FromInt(0))); // Indicates no initial value. | 841 __ mov(r0, Operand(Smi::FromInt(0))); // Indicates no initial value. |
842 __ Push(cp, r2, r1, r0); | 842 __ Push(cp, r2, r1, r0); |
843 } | 843 } |
844 __ CallRuntime(Runtime::kHiddenDeclareContextSlot, 4); | 844 __ CallRuntime(Runtime::kDeclareContextSlot, 4); |
845 break; | 845 break; |
846 } | 846 } |
847 } | 847 } |
848 } | 848 } |
849 | 849 |
850 | 850 |
851 void FullCodeGenerator::VisitFunctionDeclaration( | 851 void FullCodeGenerator::VisitFunctionDeclaration( |
852 FunctionDeclaration* declaration) { | 852 FunctionDeclaration* declaration) { |
853 VariableProxy* proxy = declaration->proxy(); | 853 VariableProxy* proxy = declaration->proxy(); |
854 Variable* variable = proxy->var(); | 854 Variable* variable = proxy->var(); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
890 break; | 890 break; |
891 } | 891 } |
892 | 892 |
893 case Variable::LOOKUP: { | 893 case Variable::LOOKUP: { |
894 Comment cmnt(masm_, "[ FunctionDeclaration"); | 894 Comment cmnt(masm_, "[ FunctionDeclaration"); |
895 __ mov(r2, Operand(variable->name())); | 895 __ mov(r2, Operand(variable->name())); |
896 __ mov(r1, Operand(Smi::FromInt(NONE))); | 896 __ mov(r1, Operand(Smi::FromInt(NONE))); |
897 __ Push(cp, r2, r1); | 897 __ Push(cp, r2, r1); |
898 // Push initial value for function declaration. | 898 // Push initial value for function declaration. |
899 VisitForStackValue(declaration->fun()); | 899 VisitForStackValue(declaration->fun()); |
900 __ CallRuntime(Runtime::kHiddenDeclareContextSlot, 4); | 900 __ CallRuntime(Runtime::kDeclareContextSlot, 4); |
901 break; | 901 break; |
902 } | 902 } |
903 } | 903 } |
904 } | 904 } |
905 | 905 |
906 | 906 |
907 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { | 907 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { |
908 Variable* variable = declaration->proxy()->var(); | 908 Variable* variable = declaration->proxy()->var(); |
909 ASSERT(variable->location() == Variable::CONTEXT); | 909 ASSERT(variable->location() == Variable::CONTEXT); |
910 ASSERT(variable->interface()->IsFrozen()); | 910 ASSERT(variable->interface()->IsFrozen()); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
962 // TODO(rossberg) | 962 // TODO(rossberg) |
963 } | 963 } |
964 | 964 |
965 | 965 |
966 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 966 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
967 // Call the runtime to declare the globals. | 967 // Call the runtime to declare the globals. |
968 // The context is the first argument. | 968 // The context is the first argument. |
969 __ mov(r1, Operand(pairs)); | 969 __ mov(r1, Operand(pairs)); |
970 __ mov(r0, Operand(Smi::FromInt(DeclareGlobalsFlags()))); | 970 __ mov(r0, Operand(Smi::FromInt(DeclareGlobalsFlags()))); |
971 __ Push(cp, r1, r0); | 971 __ Push(cp, r1, r0); |
972 __ CallRuntime(Runtime::kHiddenDeclareGlobals, 3); | 972 __ CallRuntime(Runtime::kDeclareGlobals, 3); |
973 // Return value is ignored. | 973 // Return value is ignored. |
974 } | 974 } |
975 | 975 |
976 | 976 |
977 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { | 977 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { |
978 // Call the runtime to declare the modules. | 978 // Call the runtime to declare the modules. |
979 __ Push(descriptions); | 979 __ Push(descriptions); |
980 __ CallRuntime(Runtime::kHiddenDeclareModules, 1); | 980 __ CallRuntime(Runtime::kDeclareModules, 1); |
981 // Return value is ignored. | 981 // Return value is ignored. |
982 } | 982 } |
983 | 983 |
984 | 984 |
985 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 985 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
986 Comment cmnt(masm_, "[ SwitchStatement"); | 986 Comment cmnt(masm_, "[ SwitchStatement"); |
987 Breakable nested_statement(this, stmt); | 987 Breakable nested_statement(this, stmt); |
988 SetStatementPosition(stmt); | 988 SetStatementPosition(stmt); |
989 | 989 |
990 // Keep the switch value on the stack until a case matches. | 990 // Keep the switch value on the stack until a case matches. |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1322 FastNewClosureStub stub(isolate(), | 1322 FastNewClosureStub stub(isolate(), |
1323 info->strict_mode(), | 1323 info->strict_mode(), |
1324 info->is_generator()); | 1324 info->is_generator()); |
1325 __ mov(r2, Operand(info)); | 1325 __ mov(r2, Operand(info)); |
1326 __ CallStub(&stub); | 1326 __ CallStub(&stub); |
1327 } else { | 1327 } else { |
1328 __ mov(r0, Operand(info)); | 1328 __ mov(r0, Operand(info)); |
1329 __ LoadRoot(r1, pretenure ? Heap::kTrueValueRootIndex | 1329 __ LoadRoot(r1, pretenure ? Heap::kTrueValueRootIndex |
1330 : Heap::kFalseValueRootIndex); | 1330 : Heap::kFalseValueRootIndex); |
1331 __ Push(cp, r0, r1); | 1331 __ Push(cp, r0, r1); |
1332 __ CallRuntime(Runtime::kHiddenNewClosure, 3); | 1332 __ CallRuntime(Runtime::kNewClosure, 3); |
1333 } | 1333 } |
1334 context()->Plug(r0); | 1334 context()->Plug(r0); |
1335 } | 1335 } |
1336 | 1336 |
1337 | 1337 |
1338 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 1338 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
1339 Comment cmnt(masm_, "[ VariableProxy"); | 1339 Comment cmnt(masm_, "[ VariableProxy"); |
1340 EmitVariableLoad(expr); | 1340 EmitVariableLoad(expr); |
1341 } | 1341 } |
1342 | 1342 |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1447 __ ldr(r0, ContextSlotOperandCheckExtensions(local, slow)); | 1447 __ ldr(r0, ContextSlotOperandCheckExtensions(local, slow)); |
1448 if (local->mode() == LET || local->mode() == CONST || | 1448 if (local->mode() == LET || local->mode() == CONST || |
1449 local->mode() == CONST_LEGACY) { | 1449 local->mode() == CONST_LEGACY) { |
1450 __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); | 1450 __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); |
1451 if (local->mode() == CONST_LEGACY) { | 1451 if (local->mode() == CONST_LEGACY) { |
1452 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); | 1452 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); |
1453 } else { // LET || CONST | 1453 } else { // LET || CONST |
1454 __ b(ne, done); | 1454 __ b(ne, done); |
1455 __ mov(r0, Operand(var->name())); | 1455 __ mov(r0, Operand(var->name())); |
1456 __ push(r0); | 1456 __ push(r0); |
1457 __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1); | 1457 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
1458 } | 1458 } |
1459 } | 1459 } |
1460 __ jmp(done); | 1460 __ jmp(done); |
1461 } | 1461 } |
1462 } | 1462 } |
1463 | 1463 |
1464 | 1464 |
1465 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { | 1465 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { |
1466 // Record position before possible IC call. | 1466 // Record position before possible IC call. |
1467 SetSourcePosition(proxy->position()); | 1467 SetSourcePosition(proxy->position()); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1525 // Let and const need a read barrier. | 1525 // Let and const need a read barrier. |
1526 GetVar(r0, var); | 1526 GetVar(r0, var); |
1527 __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); | 1527 __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); |
1528 if (var->mode() == LET || var->mode() == CONST) { | 1528 if (var->mode() == LET || var->mode() == CONST) { |
1529 // Throw a reference error when using an uninitialized let/const | 1529 // Throw a reference error when using an uninitialized let/const |
1530 // binding in harmony mode. | 1530 // binding in harmony mode. |
1531 Label done; | 1531 Label done; |
1532 __ b(ne, &done); | 1532 __ b(ne, &done); |
1533 __ mov(r0, Operand(var->name())); | 1533 __ mov(r0, Operand(var->name())); |
1534 __ push(r0); | 1534 __ push(r0); |
1535 __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1); | 1535 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
1536 __ bind(&done); | 1536 __ bind(&done); |
1537 } else { | 1537 } else { |
1538 // Uninitalized const bindings outside of harmony mode are unholed. | 1538 // Uninitalized const bindings outside of harmony mode are unholed. |
1539 ASSERT(var->mode() == CONST_LEGACY); | 1539 ASSERT(var->mode() == CONST_LEGACY); |
1540 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); | 1540 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); |
1541 } | 1541 } |
1542 context()->Plug(r0); | 1542 context()->Plug(r0); |
1543 break; | 1543 break; |
1544 } | 1544 } |
1545 } | 1545 } |
1546 context()->Plug(var); | 1546 context()->Plug(var); |
1547 break; | 1547 break; |
1548 } | 1548 } |
1549 | 1549 |
1550 case Variable::LOOKUP: { | 1550 case Variable::LOOKUP: { |
1551 Comment cmnt(masm_, "[ Lookup variable"); | 1551 Comment cmnt(masm_, "[ Lookup variable"); |
1552 Label done, slow; | 1552 Label done, slow; |
1553 // Generate code for loading from variables potentially shadowed | 1553 // Generate code for loading from variables potentially shadowed |
1554 // by eval-introduced variables. | 1554 // by eval-introduced variables. |
1555 EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done); | 1555 EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done); |
1556 __ bind(&slow); | 1556 __ bind(&slow); |
1557 __ mov(r1, Operand(var->name())); | 1557 __ mov(r1, Operand(var->name())); |
1558 __ Push(cp, r1); // Context and name. | 1558 __ Push(cp, r1); // Context and name. |
1559 __ CallRuntime(Runtime::kHiddenLoadContextSlot, 2); | 1559 __ CallRuntime(Runtime::kLoadContextSlot, 2); |
1560 __ bind(&done); | 1560 __ bind(&done); |
1561 context()->Plug(r0); | 1561 context()->Plug(r0); |
1562 } | 1562 } |
1563 } | 1563 } |
1564 } | 1564 } |
1565 | 1565 |
1566 | 1566 |
1567 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1567 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
1568 Comment cmnt(masm_, "[ RegExpLiteral"); | 1568 Comment cmnt(masm_, "[ RegExpLiteral"); |
1569 Label materialized; | 1569 Label materialized; |
(...skipping 12 matching lines...) Expand all Loading... |
1582 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 1582 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
1583 __ cmp(r5, ip); | 1583 __ cmp(r5, ip); |
1584 __ b(ne, &materialized); | 1584 __ b(ne, &materialized); |
1585 | 1585 |
1586 // Create regexp literal using runtime function. | 1586 // Create regexp literal using runtime function. |
1587 // Result will be in r0. | 1587 // Result will be in r0. |
1588 __ mov(r3, Operand(Smi::FromInt(expr->literal_index()))); | 1588 __ mov(r3, Operand(Smi::FromInt(expr->literal_index()))); |
1589 __ mov(r2, Operand(expr->pattern())); | 1589 __ mov(r2, Operand(expr->pattern())); |
1590 __ mov(r1, Operand(expr->flags())); | 1590 __ mov(r1, Operand(expr->flags())); |
1591 __ Push(r4, r3, r2, r1); | 1591 __ Push(r4, r3, r2, r1); |
1592 __ CallRuntime(Runtime::kHiddenMaterializeRegExpLiteral, 4); | 1592 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
1593 __ mov(r5, r0); | 1593 __ mov(r5, r0); |
1594 | 1594 |
1595 __ bind(&materialized); | 1595 __ bind(&materialized); |
1596 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; | 1596 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; |
1597 Label allocated, runtime_allocate; | 1597 Label allocated, runtime_allocate; |
1598 __ Allocate(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT); | 1598 __ Allocate(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT); |
1599 __ jmp(&allocated); | 1599 __ jmp(&allocated); |
1600 | 1600 |
1601 __ bind(&runtime_allocate); | 1601 __ bind(&runtime_allocate); |
1602 __ mov(r0, Operand(Smi::FromInt(size))); | 1602 __ mov(r0, Operand(Smi::FromInt(size))); |
1603 __ Push(r5, r0); | 1603 __ Push(r5, r0); |
1604 __ CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1); | 1604 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
1605 __ pop(r5); | 1605 __ pop(r5); |
1606 | 1606 |
1607 __ bind(&allocated); | 1607 __ bind(&allocated); |
1608 // After this, registers are used as follows: | 1608 // After this, registers are used as follows: |
1609 // r0: Newly allocated regexp. | 1609 // r0: Newly allocated regexp. |
1610 // r5: Materialized regexp. | 1610 // r5: Materialized regexp. |
1611 // r2: temp. | 1611 // r2: temp. |
1612 __ CopyFields(r0, r5, d0, size / kPointerSize); | 1612 __ CopyFields(r0, r5, d0, size / kPointerSize); |
1613 context()->Plug(r0); | 1613 context()->Plug(r0); |
1614 } | 1614 } |
(...skipping 23 matching lines...) Expand all Loading... |
1638 : ObjectLiteral::kNoFlags; | 1638 : ObjectLiteral::kNoFlags; |
1639 flags |= expr->has_function() | 1639 flags |= expr->has_function() |
1640 ? ObjectLiteral::kHasFunction | 1640 ? ObjectLiteral::kHasFunction |
1641 : ObjectLiteral::kNoFlags; | 1641 : ObjectLiteral::kNoFlags; |
1642 __ mov(r0, Operand(Smi::FromInt(flags))); | 1642 __ mov(r0, Operand(Smi::FromInt(flags))); |
1643 int properties_count = constant_properties->length() / 2; | 1643 int properties_count = constant_properties->length() / 2; |
1644 if (expr->may_store_doubles() || expr->depth() > 1 || | 1644 if (expr->may_store_doubles() || expr->depth() > 1 || |
1645 masm()->serializer_enabled() || flags != ObjectLiteral::kFastElements || | 1645 masm()->serializer_enabled() || flags != ObjectLiteral::kFastElements || |
1646 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { | 1646 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { |
1647 __ Push(r3, r2, r1, r0); | 1647 __ Push(r3, r2, r1, r0); |
1648 __ CallRuntime(Runtime::kHiddenCreateObjectLiteral, 4); | 1648 __ CallRuntime(Runtime::kCreateObjectLiteral, 4); |
1649 } else { | 1649 } else { |
1650 FastCloneShallowObjectStub stub(isolate(), properties_count); | 1650 FastCloneShallowObjectStub stub(isolate(), properties_count); |
1651 __ CallStub(&stub); | 1651 __ CallStub(&stub); |
1652 } | 1652 } |
1653 | 1653 |
1654 // If result_saved is true the result is on top of the stack. If | 1654 // If result_saved is true the result is on top of the stack. If |
1655 // result_saved is false the result is in r0. | 1655 // result_saved is false the result is in r0. |
1656 bool result_saved = false; | 1656 bool result_saved = false; |
1657 | 1657 |
1658 // Mark all computed expressions that are bound to a key that | 1658 // Mark all computed expressions that are bound to a key that |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1779 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; | 1779 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; |
1780 } | 1780 } |
1781 | 1781 |
1782 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1782 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
1783 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); | 1783 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); |
1784 __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); | 1784 __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); |
1785 __ mov(r1, Operand(constant_elements)); | 1785 __ mov(r1, Operand(constant_elements)); |
1786 if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) { | 1786 if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) { |
1787 __ mov(r0, Operand(Smi::FromInt(flags))); | 1787 __ mov(r0, Operand(Smi::FromInt(flags))); |
1788 __ Push(r3, r2, r1, r0); | 1788 __ Push(r3, r2, r1, r0); |
1789 __ CallRuntime(Runtime::kHiddenCreateArrayLiteral, 4); | 1789 __ CallRuntime(Runtime::kCreateArrayLiteral, 4); |
1790 } else { | 1790 } else { |
1791 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); | 1791 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); |
1792 __ CallStub(&stub); | 1792 __ CallStub(&stub); |
1793 } | 1793 } |
1794 | 1794 |
1795 bool result_saved = false; // Is the result saved to the stack? | 1795 bool result_saved = false; // Is the result saved to the stack? |
1796 | 1796 |
1797 // Emit code to evaluate all the non-constant subexpressions and to store | 1797 // Emit code to evaluate all the non-constant subexpressions and to store |
1798 // them into the newly cloned array. | 1798 // them into the newly cloned array. |
1799 for (int i = 0; i < length; i++) { | 1799 for (int i = 0; i < length; i++) { |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1971 __ mov(r1, Operand(Smi::FromInt(continuation.pos()))); | 1971 __ mov(r1, Operand(Smi::FromInt(continuation.pos()))); |
1972 __ str(r1, FieldMemOperand(r0, JSGeneratorObject::kContinuationOffset)); | 1972 __ str(r1, FieldMemOperand(r0, JSGeneratorObject::kContinuationOffset)); |
1973 __ str(cp, FieldMemOperand(r0, JSGeneratorObject::kContextOffset)); | 1973 __ str(cp, FieldMemOperand(r0, JSGeneratorObject::kContextOffset)); |
1974 __ mov(r1, cp); | 1974 __ mov(r1, cp); |
1975 __ RecordWriteField(r0, JSGeneratorObject::kContextOffset, r1, r2, | 1975 __ RecordWriteField(r0, JSGeneratorObject::kContextOffset, r1, r2, |
1976 kLRHasBeenSaved, kDontSaveFPRegs); | 1976 kLRHasBeenSaved, kDontSaveFPRegs); |
1977 __ add(r1, fp, Operand(StandardFrameConstants::kExpressionsOffset)); | 1977 __ add(r1, fp, Operand(StandardFrameConstants::kExpressionsOffset)); |
1978 __ cmp(sp, r1); | 1978 __ cmp(sp, r1); |
1979 __ b(eq, &post_runtime); | 1979 __ b(eq, &post_runtime); |
1980 __ push(r0); // generator object | 1980 __ push(r0); // generator object |
1981 __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1); | 1981 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
1982 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1982 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
1983 __ bind(&post_runtime); | 1983 __ bind(&post_runtime); |
1984 __ pop(result_register()); | 1984 __ pop(result_register()); |
1985 EmitReturnSequence(); | 1985 EmitReturnSequence(); |
1986 | 1986 |
1987 __ bind(&resume); | 1987 __ bind(&resume); |
1988 context()->Plug(result_register()); | 1988 context()->Plug(result_register()); |
1989 break; | 1989 break; |
1990 } | 1990 } |
1991 | 1991 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2037 const int generator_object_depth = kPointerSize + handler_size; | 2037 const int generator_object_depth = kPointerSize + handler_size; |
2038 __ ldr(r0, MemOperand(sp, generator_object_depth)); | 2038 __ ldr(r0, MemOperand(sp, generator_object_depth)); |
2039 __ push(r0); // g | 2039 __ push(r0); // g |
2040 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); | 2040 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); |
2041 __ mov(r1, Operand(Smi::FromInt(l_continuation.pos()))); | 2041 __ mov(r1, Operand(Smi::FromInt(l_continuation.pos()))); |
2042 __ str(r1, FieldMemOperand(r0, JSGeneratorObject::kContinuationOffset)); | 2042 __ str(r1, FieldMemOperand(r0, JSGeneratorObject::kContinuationOffset)); |
2043 __ str(cp, FieldMemOperand(r0, JSGeneratorObject::kContextOffset)); | 2043 __ str(cp, FieldMemOperand(r0, JSGeneratorObject::kContextOffset)); |
2044 __ mov(r1, cp); | 2044 __ mov(r1, cp); |
2045 __ RecordWriteField(r0, JSGeneratorObject::kContextOffset, r1, r2, | 2045 __ RecordWriteField(r0, JSGeneratorObject::kContextOffset, r1, r2, |
2046 kLRHasBeenSaved, kDontSaveFPRegs); | 2046 kLRHasBeenSaved, kDontSaveFPRegs); |
2047 __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1); | 2047 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
2048 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2048 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2049 __ pop(r0); // result | 2049 __ pop(r0); // result |
2050 EmitReturnSequence(); | 2050 EmitReturnSequence(); |
2051 __ bind(&l_resume); // received in r0 | 2051 __ bind(&l_resume); // received in r0 |
2052 __ PopTryHandler(); | 2052 __ PopTryHandler(); |
2053 | 2053 |
2054 // receiver = iter; f = 'next'; arg = received; | 2054 // receiver = iter; f = 'next'; arg = received; |
2055 __ bind(&l_next); | 2055 __ bind(&l_next); |
2056 __ LoadRoot(r2, Heap::knext_stringRootIndex); // "next" | 2056 __ LoadRoot(r2, Heap::knext_stringRootIndex); // "next" |
2057 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter | 2057 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2089 break; | 2089 break; |
2090 } | 2090 } |
2091 } | 2091 } |
2092 } | 2092 } |
2093 | 2093 |
2094 | 2094 |
2095 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, | 2095 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, |
2096 Expression *value, | 2096 Expression *value, |
2097 JSGeneratorObject::ResumeMode resume_mode) { | 2097 JSGeneratorObject::ResumeMode resume_mode) { |
2098 // The value stays in r0, and is ultimately read by the resumed generator, as | 2098 // The value stays in r0, and is ultimately read by the resumed generator, as |
2099 // if CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject) returned it. Or it | 2099 // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it |
2100 // is read to throw the value when the resumed generator is already closed. | 2100 // is read to throw the value when the resumed generator is already closed. |
2101 // r1 will hold the generator object until the activation has been resumed. | 2101 // r1 will hold the generator object until the activation has been resumed. |
2102 VisitForStackValue(generator); | 2102 VisitForStackValue(generator); |
2103 VisitForAccumulatorValue(value); | 2103 VisitForAccumulatorValue(value); |
2104 __ pop(r1); | 2104 __ pop(r1); |
2105 | 2105 |
2106 // Check generator state. | 2106 // Check generator state. |
2107 Label wrong_state, closed_state, done; | 2107 Label wrong_state, closed_state, done; |
2108 __ ldr(r3, FieldMemOperand(r1, JSGeneratorObject::kContinuationOffset)); | 2108 __ ldr(r3, FieldMemOperand(r1, JSGeneratorObject::kContinuationOffset)); |
2109 STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0); | 2109 STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2183 Label push_operand_holes, call_resume; | 2183 Label push_operand_holes, call_resume; |
2184 __ bind(&push_operand_holes); | 2184 __ bind(&push_operand_holes); |
2185 __ sub(r3, r3, Operand(1), SetCC); | 2185 __ sub(r3, r3, Operand(1), SetCC); |
2186 __ b(mi, &call_resume); | 2186 __ b(mi, &call_resume); |
2187 __ push(r2); | 2187 __ push(r2); |
2188 __ b(&push_operand_holes); | 2188 __ b(&push_operand_holes); |
2189 __ bind(&call_resume); | 2189 __ bind(&call_resume); |
2190 ASSERT(!result_register().is(r1)); | 2190 ASSERT(!result_register().is(r1)); |
2191 __ Push(r1, result_register()); | 2191 __ Push(r1, result_register()); |
2192 __ Push(Smi::FromInt(resume_mode)); | 2192 __ Push(Smi::FromInt(resume_mode)); |
2193 __ CallRuntime(Runtime::kHiddenResumeJSGeneratorObject, 3); | 2193 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); |
2194 // Not reached: the runtime call returns elsewhere. | 2194 // Not reached: the runtime call returns elsewhere. |
2195 __ stop("not-reached"); | 2195 __ stop("not-reached"); |
2196 | 2196 |
2197 // Reach here when generator is closed. | 2197 // Reach here when generator is closed. |
2198 __ bind(&closed_state); | 2198 __ bind(&closed_state); |
2199 if (resume_mode == JSGeneratorObject::NEXT) { | 2199 if (resume_mode == JSGeneratorObject::NEXT) { |
2200 // Return completed iterator result when generator is closed. | 2200 // Return completed iterator result when generator is closed. |
2201 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); | 2201 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); |
2202 __ push(r2); | 2202 __ push(r2); |
2203 // Pop value from top-of-stack slot; box result into result register. | 2203 // Pop value from top-of-stack slot; box result into result register. |
2204 EmitCreateIteratorResult(true); | 2204 EmitCreateIteratorResult(true); |
2205 } else { | 2205 } else { |
2206 // Throw the provided value. | 2206 // Throw the provided value. |
2207 __ push(r0); | 2207 __ push(r0); |
2208 __ CallRuntime(Runtime::kHiddenThrow, 1); | 2208 __ CallRuntime(Runtime::kThrow, 1); |
2209 } | 2209 } |
2210 __ jmp(&done); | 2210 __ jmp(&done); |
2211 | 2211 |
2212 // Throw error if we attempt to operate on a running generator. | 2212 // Throw error if we attempt to operate on a running generator. |
2213 __ bind(&wrong_state); | 2213 __ bind(&wrong_state); |
2214 __ push(r1); | 2214 __ push(r1); |
2215 __ CallRuntime(Runtime::kHiddenThrowGeneratorStateError, 1); | 2215 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); |
2216 | 2216 |
2217 __ bind(&done); | 2217 __ bind(&done); |
2218 context()->Plug(result_register()); | 2218 context()->Plug(result_register()); |
2219 } | 2219 } |
2220 | 2220 |
2221 | 2221 |
2222 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { | 2222 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { |
2223 Label gc_required; | 2223 Label gc_required; |
2224 Label allocated; | 2224 Label allocated; |
2225 | 2225 |
2226 Handle<Map> map(isolate()->native_context()->iterator_result_map()); | 2226 Handle<Map> map(isolate()->native_context()->iterator_result_map()); |
2227 | 2227 |
2228 __ Allocate(map->instance_size(), r0, r2, r3, &gc_required, TAG_OBJECT); | 2228 __ Allocate(map->instance_size(), r0, r2, r3, &gc_required, TAG_OBJECT); |
2229 __ jmp(&allocated); | 2229 __ jmp(&allocated); |
2230 | 2230 |
2231 __ bind(&gc_required); | 2231 __ bind(&gc_required); |
2232 __ Push(Smi::FromInt(map->instance_size())); | 2232 __ Push(Smi::FromInt(map->instance_size())); |
2233 __ CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1); | 2233 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
2234 __ ldr(context_register(), | 2234 __ ldr(context_register(), |
2235 MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2235 MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2236 | 2236 |
2237 __ bind(&allocated); | 2237 __ bind(&allocated); |
2238 __ mov(r1, Operand(map)); | 2238 __ mov(r1, Operand(map)); |
2239 __ pop(r2); | 2239 __ pop(r2); |
2240 __ mov(r3, Operand(isolate()->factory()->ToBoolean(done))); | 2240 __ mov(r3, Operand(isolate()->factory()->ToBoolean(done))); |
2241 __ mov(r4, Operand(isolate()->factory()->empty_fixed_array())); | 2241 __ mov(r4, Operand(isolate()->factory()->empty_fixed_array())); |
2242 ASSERT_EQ(map->instance_size(), 5 * kPointerSize); | 2242 ASSERT_EQ(map->instance_size(), 5 * kPointerSize); |
2243 __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); | 2243 __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2437 } | 2437 } |
2438 } | 2438 } |
2439 | 2439 |
2440 | 2440 |
2441 void FullCodeGenerator::EmitCallStoreContextSlot( | 2441 void FullCodeGenerator::EmitCallStoreContextSlot( |
2442 Handle<String> name, StrictMode strict_mode) { | 2442 Handle<String> name, StrictMode strict_mode) { |
2443 __ push(r0); // Value. | 2443 __ push(r0); // Value. |
2444 __ mov(r1, Operand(name)); | 2444 __ mov(r1, Operand(name)); |
2445 __ mov(r0, Operand(Smi::FromInt(strict_mode))); | 2445 __ mov(r0, Operand(Smi::FromInt(strict_mode))); |
2446 __ Push(cp, r1, r0); // Context, name, strict mode. | 2446 __ Push(cp, r1, r0); // Context, name, strict mode. |
2447 __ CallRuntime(Runtime::kHiddenStoreContextSlot, 4); | 2447 __ CallRuntime(Runtime::kStoreContextSlot, 4); |
2448 } | 2448 } |
2449 | 2449 |
2450 | 2450 |
2451 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { | 2451 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { |
2452 if (var->IsUnallocated()) { | 2452 if (var->IsUnallocated()) { |
2453 // Global var, const, or let. | 2453 // Global var, const, or let. |
2454 __ mov(r2, Operand(var->name())); | 2454 __ mov(r2, Operand(var->name())); |
2455 __ ldr(r1, GlobalObjectOperand()); | 2455 __ ldr(r1, GlobalObjectOperand()); |
2456 CallStoreIC(); | 2456 CallStoreIC(); |
2457 | 2457 |
2458 } else if (op == Token::INIT_CONST_LEGACY) { | 2458 } else if (op == Token::INIT_CONST_LEGACY) { |
2459 // Const initializers need a write barrier. | 2459 // Const initializers need a write barrier. |
2460 ASSERT(!var->IsParameter()); // No const parameters. | 2460 ASSERT(!var->IsParameter()); // No const parameters. |
2461 if (var->IsLookupSlot()) { | 2461 if (var->IsLookupSlot()) { |
2462 __ push(r0); | 2462 __ push(r0); |
2463 __ mov(r0, Operand(var->name())); | 2463 __ mov(r0, Operand(var->name())); |
2464 __ Push(cp, r0); // Context and name. | 2464 __ Push(cp, r0); // Context and name. |
2465 __ CallRuntime(Runtime::kHiddenInitializeConstContextSlot, 3); | 2465 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
2466 } else { | 2466 } else { |
2467 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 2467 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); |
2468 Label skip; | 2468 Label skip; |
2469 MemOperand location = VarOperand(var, r1); | 2469 MemOperand location = VarOperand(var, r1); |
2470 __ ldr(r2, location); | 2470 __ ldr(r2, location); |
2471 __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); | 2471 __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); |
2472 __ b(ne, &skip); | 2472 __ b(ne, &skip); |
2473 EmitStoreToStackLocalOrContextSlot(var, location); | 2473 EmitStoreToStackLocalOrContextSlot(var, location); |
2474 __ bind(&skip); | 2474 __ bind(&skip); |
2475 } | 2475 } |
2476 | 2476 |
2477 } else if (var->mode() == LET && op != Token::INIT_LET) { | 2477 } else if (var->mode() == LET && op != Token::INIT_LET) { |
2478 // Non-initializing assignment to let variable needs a write barrier. | 2478 // Non-initializing assignment to let variable needs a write barrier. |
2479 if (var->IsLookupSlot()) { | 2479 if (var->IsLookupSlot()) { |
2480 EmitCallStoreContextSlot(var->name(), strict_mode()); | 2480 EmitCallStoreContextSlot(var->name(), strict_mode()); |
2481 } else { | 2481 } else { |
2482 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 2482 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); |
2483 Label assign; | 2483 Label assign; |
2484 MemOperand location = VarOperand(var, r1); | 2484 MemOperand location = VarOperand(var, r1); |
2485 __ ldr(r3, location); | 2485 __ ldr(r3, location); |
2486 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); | 2486 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); |
2487 __ b(ne, &assign); | 2487 __ b(ne, &assign); |
2488 __ mov(r3, Operand(var->name())); | 2488 __ mov(r3, Operand(var->name())); |
2489 __ push(r3); | 2489 __ push(r3); |
2490 __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1); | 2490 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
2491 // Perform the assignment. | 2491 // Perform the assignment. |
2492 __ bind(&assign); | 2492 __ bind(&assign); |
2493 EmitStoreToStackLocalOrContextSlot(var, location); | 2493 EmitStoreToStackLocalOrContextSlot(var, location); |
2494 } | 2494 } |
2495 | 2495 |
2496 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { | 2496 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { |
2497 // Assignment to var or initializing assignment to let/const | 2497 // Assignment to var or initializing assignment to let/const |
2498 // in harmony mode. | 2498 // in harmony mode. |
2499 if (var->IsLookupSlot()) { | 2499 if (var->IsLookupSlot()) { |
2500 EmitCallStoreContextSlot(var->name(), strict_mode()); | 2500 EmitCallStoreContextSlot(var->name(), strict_mode()); |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2674 __ ldr(r3, MemOperand(fp, receiver_offset * kPointerSize)); | 2674 __ ldr(r3, MemOperand(fp, receiver_offset * kPointerSize)); |
2675 | 2675 |
2676 // r2: strict mode. | 2676 // r2: strict mode. |
2677 __ mov(r2, Operand(Smi::FromInt(strict_mode()))); | 2677 __ mov(r2, Operand(Smi::FromInt(strict_mode()))); |
2678 | 2678 |
2679 // r1: the start position of the scope the calls resides in. | 2679 // r1: the start position of the scope the calls resides in. |
2680 __ mov(r1, Operand(Smi::FromInt(scope()->start_position()))); | 2680 __ mov(r1, Operand(Smi::FromInt(scope()->start_position()))); |
2681 | 2681 |
2682 // Do the runtime call. | 2682 // Do the runtime call. |
2683 __ Push(r4, r3, r2, r1); | 2683 __ Push(r4, r3, r2, r1); |
2684 __ CallRuntime(Runtime::kHiddenResolvePossiblyDirectEval, 5); | 2684 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); |
2685 } | 2685 } |
2686 | 2686 |
2687 | 2687 |
2688 void FullCodeGenerator::VisitCall(Call* expr) { | 2688 void FullCodeGenerator::VisitCall(Call* expr) { |
2689 #ifdef DEBUG | 2689 #ifdef DEBUG |
2690 // We want to verify that RecordJSReturnSite gets called on all paths | 2690 // We want to verify that RecordJSReturnSite gets called on all paths |
2691 // through this function. Avoid early returns. | 2691 // through this function. Avoid early returns. |
2692 expr->return_is_recorded_ = false; | 2692 expr->return_is_recorded_ = false; |
2693 #endif | 2693 #endif |
2694 | 2694 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2748 // by eval-introduced variables. | 2748 // by eval-introduced variables. |
2749 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); | 2749 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); |
2750 } | 2750 } |
2751 | 2751 |
2752 __ bind(&slow); | 2752 __ bind(&slow); |
2753 // Call the runtime to find the function to call (returned in r0) | 2753 // Call the runtime to find the function to call (returned in r0) |
2754 // and the object holding it (returned in edx). | 2754 // and the object holding it (returned in edx). |
2755 ASSERT(!context_register().is(r2)); | 2755 ASSERT(!context_register().is(r2)); |
2756 __ mov(r2, Operand(proxy->name())); | 2756 __ mov(r2, Operand(proxy->name())); |
2757 __ Push(context_register(), r2); | 2757 __ Push(context_register(), r2); |
2758 __ CallRuntime(Runtime::kHiddenLoadContextSlot, 2); | 2758 __ CallRuntime(Runtime::kLoadContextSlot, 2); |
2759 __ Push(r0, r1); // Function, receiver. | 2759 __ Push(r0, r1); // Function, receiver. |
2760 | 2760 |
2761 // If fast case code has been generated, emit code to push the | 2761 // If fast case code has been generated, emit code to push the |
2762 // function and receiver and have the slow path jump around this | 2762 // function and receiver and have the slow path jump around this |
2763 // code. | 2763 // code. |
2764 if (done.is_linked()) { | 2764 if (done.is_linked()) { |
2765 Label call; | 2765 Label call; |
2766 __ b(&call); | 2766 __ b(&call); |
2767 __ bind(&done); | 2767 __ bind(&done); |
2768 // Push function. | 2768 // Push function. |
(...skipping 608 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3377 __ jmp(&done); | 3377 __ jmp(&done); |
3378 } | 3378 } |
3379 __ bind(&runtime); | 3379 __ bind(&runtime); |
3380 __ PrepareCallCFunction(2, scratch1); | 3380 __ PrepareCallCFunction(2, scratch1); |
3381 __ mov(r1, Operand(index)); | 3381 __ mov(r1, Operand(index)); |
3382 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); | 3382 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); |
3383 __ jmp(&done); | 3383 __ jmp(&done); |
3384 } | 3384 } |
3385 | 3385 |
3386 __ bind(¬_date_object); | 3386 __ bind(¬_date_object); |
3387 __ CallRuntime(Runtime::kHiddenThrowNotDateError, 0); | 3387 __ CallRuntime(Runtime::kThrowNotDateError, 0); |
3388 __ bind(&done); | 3388 __ bind(&done); |
3389 context()->Plug(r0); | 3389 context()->Plug(r0); |
3390 } | 3390 } |
3391 | 3391 |
3392 | 3392 |
3393 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { | 3393 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { |
3394 ZoneList<Expression*>* args = expr->arguments(); | 3394 ZoneList<Expression*>* args = expr->arguments(); |
3395 ASSERT_EQ(3, args->length()); | 3395 ASSERT_EQ(3, args->length()); |
3396 | 3396 |
3397 Register string = r0; | 3397 Register string = r0; |
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3726 // Note side effect of PreIndex: r3 now points to the key of the pair. | 3726 // Note side effect of PreIndex: r3 now points to the key of the pair. |
3727 __ cmp(key, r2); | 3727 __ cmp(key, r2); |
3728 __ b(ne, ¬_found); | 3728 __ b(ne, ¬_found); |
3729 | 3729 |
3730 __ ldr(r0, MemOperand(r3, kPointerSize)); | 3730 __ ldr(r0, MemOperand(r3, kPointerSize)); |
3731 __ b(&done); | 3731 __ b(&done); |
3732 | 3732 |
3733 __ bind(¬_found); | 3733 __ bind(¬_found); |
3734 // Call runtime to perform the lookup. | 3734 // Call runtime to perform the lookup. |
3735 __ Push(cache, key); | 3735 __ Push(cache, key); |
3736 __ CallRuntime(Runtime::kHiddenGetFromCache, 2); | 3736 __ CallRuntime(Runtime::kGetFromCache, 2); |
3737 | 3737 |
3738 __ bind(&done); | 3738 __ bind(&done); |
3739 context()->Plug(r0); | 3739 context()->Plug(r0); |
3740 } | 3740 } |
3741 | 3741 |
3742 | 3742 |
3743 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { | 3743 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { |
3744 ZoneList<Expression*>* args = expr->arguments(); | 3744 ZoneList<Expression*>* args = expr->arguments(); |
3745 VisitForAccumulatorValue(args->at(0)); | 3745 VisitForAccumulatorValue(args->at(0)); |
3746 | 3746 |
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4105 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4105 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
4106 // Result of deleting non-global, non-dynamic variables is false. | 4106 // Result of deleting non-global, non-dynamic variables is false. |
4107 // The subexpression does not have side effects. | 4107 // The subexpression does not have side effects. |
4108 context()->Plug(var->is_this()); | 4108 context()->Plug(var->is_this()); |
4109 } else { | 4109 } else { |
4110 // Non-global variable. Call the runtime to try to delete from the | 4110 // Non-global variable. Call the runtime to try to delete from the |
4111 // context where the variable was introduced. | 4111 // context where the variable was introduced. |
4112 ASSERT(!context_register().is(r2)); | 4112 ASSERT(!context_register().is(r2)); |
4113 __ mov(r2, Operand(var->name())); | 4113 __ mov(r2, Operand(var->name())); |
4114 __ Push(context_register(), r2); | 4114 __ Push(context_register(), r2); |
4115 __ CallRuntime(Runtime::kHiddenDeleteContextSlot, 2); | 4115 __ CallRuntime(Runtime::kDeleteContextSlot, 2); |
4116 context()->Plug(r0); | 4116 context()->Plug(r0); |
4117 } | 4117 } |
4118 } else { | 4118 } else { |
4119 // Result of deleting non-property, non-variable reference is true. | 4119 // Result of deleting non-property, non-variable reference is true. |
4120 // The subexpression may have side effects. | 4120 // The subexpression may have side effects. |
4121 VisitForEffect(expr->expression()); | 4121 VisitForEffect(expr->expression()); |
4122 context()->Plug(true); | 4122 context()->Plug(true); |
4123 } | 4123 } |
4124 break; | 4124 break; |
4125 } | 4125 } |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4382 Comment cmnt(masm_, "[ Lookup slot"); | 4382 Comment cmnt(masm_, "[ Lookup slot"); |
4383 Label done, slow; | 4383 Label done, slow; |
4384 | 4384 |
4385 // Generate code for loading from variables potentially shadowed | 4385 // Generate code for loading from variables potentially shadowed |
4386 // by eval-introduced variables. | 4386 // by eval-introduced variables. |
4387 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); | 4387 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); |
4388 | 4388 |
4389 __ bind(&slow); | 4389 __ bind(&slow); |
4390 __ mov(r0, Operand(proxy->name())); | 4390 __ mov(r0, Operand(proxy->name())); |
4391 __ Push(cp, r0); | 4391 __ Push(cp, r0); |
4392 __ CallRuntime(Runtime::kHiddenLoadContextSlotNoReferenceError, 2); | 4392 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); |
4393 PrepareForBailout(expr, TOS_REG); | 4393 PrepareForBailout(expr, TOS_REG); |
4394 __ bind(&done); | 4394 __ bind(&done); |
4395 | 4395 |
4396 context()->Plug(r0); | 4396 context()->Plug(r0); |
4397 } else { | 4397 } else { |
4398 // This expression cannot throw a reference error at the top level. | 4398 // This expression cannot throw a reference error at the top level. |
4399 VisitInDuplicateContext(expr); | 4399 VisitInDuplicateContext(expr); |
4400 } | 4400 } |
4401 } | 4401 } |
4402 | 4402 |
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4821 | 4821 |
4822 ASSERT(interrupt_address == | 4822 ASSERT(interrupt_address == |
4823 isolate->builtins()->OsrAfterStackCheck()->entry()); | 4823 isolate->builtins()->OsrAfterStackCheck()->entry()); |
4824 return OSR_AFTER_STACK_CHECK; | 4824 return OSR_AFTER_STACK_CHECK; |
4825 } | 4825 } |
4826 | 4826 |
4827 | 4827 |
4828 } } // namespace v8::internal | 4828 } } // namespace v8::internal |
4829 | 4829 |
4830 #endif // V8_TARGET_ARCH_ARM | 4830 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |