| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
| 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 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 191 bool function_in_register_x1 = true; | 191 bool function_in_register_x1 = true; |
| 192 | 192 |
| 193 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 193 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 194 if (heap_slots > 0) { | 194 if (heap_slots > 0) { |
| 195 // Argument to NewContext is the function, which is still in x1. | 195 // Argument to NewContext is the function, which is still in x1. |
| 196 Comment cmnt(masm_, "[ Allocate context"); | 196 Comment cmnt(masm_, "[ Allocate context"); |
| 197 bool need_write_barrier = true; | 197 bool need_write_barrier = true; |
| 198 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) { | 198 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) { |
| 199 __ Mov(x10, Operand(info->scope()->GetScopeInfo())); | 199 __ Mov(x10, Operand(info->scope()->GetScopeInfo())); |
| 200 __ Push(x1, x10); | 200 __ Push(x1, x10); |
| 201 __ CallRuntime(Runtime::kHiddenNewGlobalContext, 2); | 201 __ CallRuntime(Runtime::kNewGlobalContext, 2); |
| 202 } else if (heap_slots <= FastNewContextStub::kMaximumSlots) { | 202 } else if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
| 203 FastNewContextStub stub(isolate(), heap_slots); | 203 FastNewContextStub stub(isolate(), heap_slots); |
| 204 __ CallStub(&stub); | 204 __ CallStub(&stub); |
| 205 // Result of FastNewContextStub is always in new space. | 205 // Result of FastNewContextStub is always in new space. |
| 206 need_write_barrier = false; | 206 need_write_barrier = false; |
| 207 } else { | 207 } else { |
| 208 __ Push(x1); | 208 __ Push(x1); |
| 209 __ CallRuntime(Runtime::kHiddenNewFunctionContext, 1); | 209 __ CallRuntime(Runtime::kNewFunctionContext, 1); |
| 210 } | 210 } |
| 211 function_in_register_x1 = false; | 211 function_in_register_x1 = false; |
| 212 // Context is returned in x0. It replaces the context passed to us. | 212 // Context is returned in x0. It replaces the context passed to us. |
| 213 // It's saved in the stack and kept live in cp. | 213 // It's saved in the stack and kept live in cp. |
| 214 __ Mov(cp, x0); | 214 __ Mov(cp, x0); |
| 215 __ Str(x0, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 215 __ Str(x0, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 216 // Copy any necessary parameters into the context. | 216 // Copy any necessary parameters into the context. |
| 217 int num_parameters = info->scope()->num_parameters(); | 217 int num_parameters = info->scope()->num_parameters(); |
| 218 for (int i = 0; i < num_parameters; i++) { | 218 for (int i = 0; i < num_parameters; i++) { |
| 219 Variable* var = scope()->parameter(i); | 219 Variable* var = scope()->parameter(i); |
| (...skipping 632 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 852 // Note: For variables we must not push an initial value (such as | 852 // Note: For variables we must not push an initial value (such as |
| 853 // 'undefined') because we may have a (legal) redeclaration and we | 853 // 'undefined') because we may have a (legal) redeclaration and we |
| 854 // must not destroy the current value. | 854 // must not destroy the current value. |
| 855 if (hole_init) { | 855 if (hole_init) { |
| 856 __ LoadRoot(x0, Heap::kTheHoleValueRootIndex); | 856 __ LoadRoot(x0, Heap::kTheHoleValueRootIndex); |
| 857 __ Push(cp, x2, x1, x0); | 857 __ Push(cp, x2, x1, x0); |
| 858 } else { | 858 } else { |
| 859 // Pushing 0 (xzr) indicates no initial value. | 859 // Pushing 0 (xzr) indicates no initial value. |
| 860 __ Push(cp, x2, x1, xzr); | 860 __ Push(cp, x2, x1, xzr); |
| 861 } | 861 } |
| 862 __ CallRuntime(Runtime::kHiddenDeclareContextSlot, 4); | 862 __ CallRuntime(Runtime::kDeclareContextSlot, 4); |
| 863 break; | 863 break; |
| 864 } | 864 } |
| 865 } | 865 } |
| 866 } | 866 } |
| 867 | 867 |
| 868 | 868 |
| 869 void FullCodeGenerator::VisitFunctionDeclaration( | 869 void FullCodeGenerator::VisitFunctionDeclaration( |
| 870 FunctionDeclaration* declaration) { | 870 FunctionDeclaration* declaration) { |
| 871 VariableProxy* proxy = declaration->proxy(); | 871 VariableProxy* proxy = declaration->proxy(); |
| 872 Variable* variable = proxy->var(); | 872 Variable* variable = proxy->var(); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 908 break; | 908 break; |
| 909 } | 909 } |
| 910 | 910 |
| 911 case Variable::LOOKUP: { | 911 case Variable::LOOKUP: { |
| 912 Comment cmnt(masm_, "[ Function Declaration"); | 912 Comment cmnt(masm_, "[ Function Declaration"); |
| 913 __ Mov(x2, Operand(variable->name())); | 913 __ Mov(x2, Operand(variable->name())); |
| 914 __ Mov(x1, Smi::FromInt(NONE)); | 914 __ Mov(x1, Smi::FromInt(NONE)); |
| 915 __ Push(cp, x2, x1); | 915 __ Push(cp, x2, x1); |
| 916 // Push initial value for function declaration. | 916 // Push initial value for function declaration. |
| 917 VisitForStackValue(declaration->fun()); | 917 VisitForStackValue(declaration->fun()); |
| 918 __ CallRuntime(Runtime::kHiddenDeclareContextSlot, 4); | 918 __ CallRuntime(Runtime::kDeclareContextSlot, 4); |
| 919 break; | 919 break; |
| 920 } | 920 } |
| 921 } | 921 } |
| 922 } | 922 } |
| 923 | 923 |
| 924 | 924 |
| 925 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { | 925 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { |
| 926 Variable* variable = declaration->proxy()->var(); | 926 Variable* variable = declaration->proxy()->var(); |
| 927 ASSERT(variable->location() == Variable::CONTEXT); | 927 ASSERT(variable->location() == Variable::CONTEXT); |
| 928 ASSERT(variable->interface()->IsFrozen()); | 928 ASSERT(variable->interface()->IsFrozen()); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 983 | 983 |
| 984 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 984 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 985 // Call the runtime to declare the globals. | 985 // Call the runtime to declare the globals. |
| 986 __ Mov(x11, Operand(pairs)); | 986 __ Mov(x11, Operand(pairs)); |
| 987 Register flags = xzr; | 987 Register flags = xzr; |
| 988 if (Smi::FromInt(DeclareGlobalsFlags())) { | 988 if (Smi::FromInt(DeclareGlobalsFlags())) { |
| 989 flags = x10; | 989 flags = x10; |
| 990 __ Mov(flags, Smi::FromInt(DeclareGlobalsFlags())); | 990 __ Mov(flags, Smi::FromInt(DeclareGlobalsFlags())); |
| 991 } | 991 } |
| 992 __ Push(cp, x11, flags); | 992 __ Push(cp, x11, flags); |
| 993 __ CallRuntime(Runtime::kHiddenDeclareGlobals, 3); | 993 __ CallRuntime(Runtime::kDeclareGlobals, 3); |
| 994 // Return value is ignored. | 994 // Return value is ignored. |
| 995 } | 995 } |
| 996 | 996 |
| 997 | 997 |
| 998 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { | 998 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { |
| 999 // Call the runtime to declare the modules. | 999 // Call the runtime to declare the modules. |
| 1000 __ Push(descriptions); | 1000 __ Push(descriptions); |
| 1001 __ CallRuntime(Runtime::kHiddenDeclareModules, 1); | 1001 __ CallRuntime(Runtime::kDeclareModules, 1); |
| 1002 // Return value is ignored. | 1002 // Return value is ignored. |
| 1003 } | 1003 } |
| 1004 | 1004 |
| 1005 | 1005 |
| 1006 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 1006 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
| 1007 ASM_LOCATION("FullCodeGenerator::VisitSwitchStatement"); | 1007 ASM_LOCATION("FullCodeGenerator::VisitSwitchStatement"); |
| 1008 Comment cmnt(masm_, "[ SwitchStatement"); | 1008 Comment cmnt(masm_, "[ SwitchStatement"); |
| 1009 Breakable nested_statement(this, stmt); | 1009 Breakable nested_statement(this, stmt); |
| 1010 SetStatementPosition(stmt); | 1010 SetStatementPosition(stmt); |
| 1011 | 1011 |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1331 FastNewClosureStub stub(isolate(), | 1331 FastNewClosureStub stub(isolate(), |
| 1332 info->strict_mode(), | 1332 info->strict_mode(), |
| 1333 info->is_generator()); | 1333 info->is_generator()); |
| 1334 __ Mov(x2, Operand(info)); | 1334 __ Mov(x2, Operand(info)); |
| 1335 __ CallStub(&stub); | 1335 __ CallStub(&stub); |
| 1336 } else { | 1336 } else { |
| 1337 __ Mov(x11, Operand(info)); | 1337 __ Mov(x11, Operand(info)); |
| 1338 __ LoadRoot(x10, pretenure ? Heap::kTrueValueRootIndex | 1338 __ LoadRoot(x10, pretenure ? Heap::kTrueValueRootIndex |
| 1339 : Heap::kFalseValueRootIndex); | 1339 : Heap::kFalseValueRootIndex); |
| 1340 __ Push(cp, x11, x10); | 1340 __ Push(cp, x11, x10); |
| 1341 __ CallRuntime(Runtime::kHiddenNewClosure, 3); | 1341 __ CallRuntime(Runtime::kNewClosure, 3); |
| 1342 } | 1342 } |
| 1343 context()->Plug(x0); | 1343 context()->Plug(x0); |
| 1344 } | 1344 } |
| 1345 | 1345 |
| 1346 | 1346 |
| 1347 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 1347 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
| 1348 Comment cmnt(masm_, "[ VariableProxy"); | 1348 Comment cmnt(masm_, "[ VariableProxy"); |
| 1349 EmitVariableLoad(expr); | 1349 EmitVariableLoad(expr); |
| 1350 } | 1350 } |
| 1351 | 1351 |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1447 Variable* local = var->local_if_not_shadowed(); | 1447 Variable* local = var->local_if_not_shadowed(); |
| 1448 __ Ldr(x0, ContextSlotOperandCheckExtensions(local, slow)); | 1448 __ Ldr(x0, ContextSlotOperandCheckExtensions(local, slow)); |
| 1449 if (local->mode() == LET || local->mode() == CONST || | 1449 if (local->mode() == LET || local->mode() == CONST || |
| 1450 local->mode() == CONST_LEGACY) { | 1450 local->mode() == CONST_LEGACY) { |
| 1451 __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, done); | 1451 __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, done); |
| 1452 if (local->mode() == CONST_LEGACY) { | 1452 if (local->mode() == CONST_LEGACY) { |
| 1453 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); | 1453 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); |
| 1454 } else { // LET || CONST | 1454 } else { // LET || CONST |
| 1455 __ Mov(x0, Operand(var->name())); | 1455 __ Mov(x0, Operand(var->name())); |
| 1456 __ Push(x0); | 1456 __ Push(x0); |
| 1457 __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1); | 1457 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 1458 } | 1458 } |
| 1459 } | 1459 } |
| 1460 __ B(done); | 1460 __ B(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 if (!skip_init_check) { | 1525 if (!skip_init_check) { |
| 1526 // Let and const need a read barrier. | 1526 // Let and const need a read barrier. |
| 1527 GetVar(x0, var); | 1527 GetVar(x0, var); |
| 1528 Label done; | 1528 Label done; |
| 1529 __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, &done); | 1529 __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, &done); |
| 1530 if (var->mode() == LET || var->mode() == CONST) { | 1530 if (var->mode() == LET || var->mode() == CONST) { |
| 1531 // Throw a reference error when using an uninitialized let/const | 1531 // Throw a reference error when using an uninitialized let/const |
| 1532 // binding in harmony mode. | 1532 // binding in harmony mode. |
| 1533 __ Mov(x0, Operand(var->name())); | 1533 __ Mov(x0, Operand(var->name())); |
| 1534 __ Push(x0); | 1534 __ Push(x0); |
| 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(x0, Heap::kUndefinedValueRootIndex); | 1540 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); |
| 1541 __ Bind(&done); | 1541 __ Bind(&done); |
| 1542 } | 1542 } |
| 1543 context()->Plug(x0); | 1543 context()->Plug(x0); |
| 1544 break; | 1544 break; |
| 1545 } | 1545 } |
| 1546 } | 1546 } |
| 1547 context()->Plug(var); | 1547 context()->Plug(var); |
| 1548 break; | 1548 break; |
| 1549 } | 1549 } |
| 1550 | 1550 |
| 1551 case Variable::LOOKUP: { | 1551 case Variable::LOOKUP: { |
| 1552 Label done, slow; | 1552 Label done, slow; |
| 1553 // Generate code for loading from variables potentially shadowed by | 1553 // Generate code for loading from variables potentially shadowed by |
| 1554 // eval-introduced variables. | 1554 // 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 Comment cmnt(masm_, "Lookup variable"); | 1557 Comment cmnt(masm_, "Lookup variable"); |
| 1558 __ Mov(x1, Operand(var->name())); | 1558 __ Mov(x1, Operand(var->name())); |
| 1559 __ Push(cp, x1); // Context and name. | 1559 __ Push(cp, x1); // Context and name. |
| 1560 __ CallRuntime(Runtime::kHiddenLoadContextSlot, 2); | 1560 __ CallRuntime(Runtime::kLoadContextSlot, 2); |
| 1561 __ Bind(&done); | 1561 __ Bind(&done); |
| 1562 context()->Plug(x0); | 1562 context()->Plug(x0); |
| 1563 break; | 1563 break; |
| 1564 } | 1564 } |
| 1565 } | 1565 } |
| 1566 } | 1566 } |
| 1567 | 1567 |
| 1568 | 1568 |
| 1569 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1569 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 1570 Comment cmnt(masm_, "[ RegExpLiteral"); | 1570 Comment cmnt(masm_, "[ RegExpLiteral"); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1582 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | 1582 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
| 1583 __ Ldr(x5, FieldMemOperand(x4, literal_offset)); | 1583 __ Ldr(x5, FieldMemOperand(x4, literal_offset)); |
| 1584 __ JumpIfNotRoot(x5, Heap::kUndefinedValueRootIndex, &materialized); | 1584 __ JumpIfNotRoot(x5, Heap::kUndefinedValueRootIndex, &materialized); |
| 1585 | 1585 |
| 1586 // Create regexp literal using runtime function. | 1586 // Create regexp literal using runtime function. |
| 1587 // Result will be in x0. | 1587 // Result will be in x0. |
| 1588 __ Mov(x3, Smi::FromInt(expr->literal_index())); | 1588 __ Mov(x3, Smi::FromInt(expr->literal_index())); |
| 1589 __ Mov(x2, Operand(expr->pattern())); | 1589 __ Mov(x2, Operand(expr->pattern())); |
| 1590 __ Mov(x1, Operand(expr->flags())); | 1590 __ Mov(x1, Operand(expr->flags())); |
| 1591 __ Push(x4, x3, x2, x1); | 1591 __ Push(x4, x3, x2, x1); |
| 1592 __ CallRuntime(Runtime::kHiddenMaterializeRegExpLiteral, 4); | 1592 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
| 1593 __ Mov(x5, x0); | 1593 __ Mov(x5, x0); |
| 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, x0, x2, x3, &runtime_allocate, TAG_OBJECT); | 1598 __ Allocate(size, x0, x2, x3, &runtime_allocate, TAG_OBJECT); |
| 1599 __ B(&allocated); | 1599 __ B(&allocated); |
| 1600 | 1600 |
| 1601 __ Bind(&runtime_allocate); | 1601 __ Bind(&runtime_allocate); |
| 1602 __ Mov(x10, Smi::FromInt(size)); | 1602 __ Mov(x10, Smi::FromInt(size)); |
| 1603 __ Push(x5, x10); | 1603 __ Push(x5, x10); |
| 1604 __ CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1); | 1604 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
| 1605 __ Pop(x5); | 1605 __ Pop(x5); |
| 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 // x0: Newly allocated regexp. | 1609 // x0: Newly allocated regexp. |
| 1610 // x5: Materialized regexp. | 1610 // x5: Materialized regexp. |
| 1611 // x10, x11, x12: temps. | 1611 // x10, x11, x12: temps. |
| 1612 __ CopyFields(x0, x5, CPURegList(x10, x11, x12), size / kPointerSize); | 1612 __ CopyFields(x0, x5, CPURegList(x10, x11, x12), size / kPointerSize); |
| 1613 context()->Plug(x0); | 1613 context()->Plug(x0); |
| 1614 } | 1614 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1640 ? ObjectLiteral::kHasFunction | 1640 ? ObjectLiteral::kHasFunction |
| 1641 : ObjectLiteral::kNoFlags; | 1641 : ObjectLiteral::kNoFlags; |
| 1642 __ Mov(x0, Smi::FromInt(flags)); | 1642 __ Mov(x0, Smi::FromInt(flags)); |
| 1643 int properties_count = constant_properties->length() / 2; | 1643 int properties_count = constant_properties->length() / 2; |
| 1644 const int max_cloned_properties = | 1644 const int max_cloned_properties = |
| 1645 FastCloneShallowObjectStub::kMaximumClonedProperties; | 1645 FastCloneShallowObjectStub::kMaximumClonedProperties; |
| 1646 if (expr->may_store_doubles() || expr->depth() > 1 || | 1646 if (expr->may_store_doubles() || expr->depth() > 1 || |
| 1647 masm()->serializer_enabled() || flags != ObjectLiteral::kFastElements || | 1647 masm()->serializer_enabled() || flags != ObjectLiteral::kFastElements || |
| 1648 properties_count > max_cloned_properties) { | 1648 properties_count > max_cloned_properties) { |
| 1649 __ Push(x3, x2, x1, x0); | 1649 __ Push(x3, x2, x1, x0); |
| 1650 __ CallRuntime(Runtime::kHiddenCreateObjectLiteral, 4); | 1650 __ CallRuntime(Runtime::kCreateObjectLiteral, 4); |
| 1651 } else { | 1651 } else { |
| 1652 FastCloneShallowObjectStub stub(isolate(), properties_count); | 1652 FastCloneShallowObjectStub stub(isolate(), properties_count); |
| 1653 __ CallStub(&stub); | 1653 __ CallStub(&stub); |
| 1654 } | 1654 } |
| 1655 | 1655 |
| 1656 // If result_saved is true the result is on top of the stack. If | 1656 // If result_saved is true the result is on top of the stack. If |
| 1657 // result_saved is false the result is in x0. | 1657 // result_saved is false the result is in x0. |
| 1658 bool result_saved = false; | 1658 bool result_saved = false; |
| 1659 | 1659 |
| 1660 // Mark all computed expressions that are bound to a key that | 1660 // Mark all computed expressions that are bound to a key that |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1780 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; | 1780 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; |
| 1781 } | 1781 } |
| 1782 | 1782 |
| 1783 __ Ldr(x3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1783 __ Ldr(x3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1784 __ Ldr(x3, FieldMemOperand(x3, JSFunction::kLiteralsOffset)); | 1784 __ Ldr(x3, FieldMemOperand(x3, JSFunction::kLiteralsOffset)); |
| 1785 __ Mov(x2, Smi::FromInt(expr->literal_index())); | 1785 __ Mov(x2, Smi::FromInt(expr->literal_index())); |
| 1786 __ Mov(x1, Operand(constant_elements)); | 1786 __ Mov(x1, Operand(constant_elements)); |
| 1787 if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) { | 1787 if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) { |
| 1788 __ Mov(x0, Smi::FromInt(flags)); | 1788 __ Mov(x0, Smi::FromInt(flags)); |
| 1789 __ Push(x3, x2, x1, x0); | 1789 __ Push(x3, x2, x1, x0); |
| 1790 __ CallRuntime(Runtime::kHiddenCreateArrayLiteral, 4); | 1790 __ CallRuntime(Runtime::kCreateArrayLiteral, 4); |
| 1791 } else { | 1791 } else { |
| 1792 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); | 1792 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); |
| 1793 __ CallStub(&stub); | 1793 __ CallStub(&stub); |
| 1794 } | 1794 } |
| 1795 | 1795 |
| 1796 bool result_saved = false; // Is the result saved to the stack? | 1796 bool result_saved = false; // Is the result saved to the stack? |
| 1797 | 1797 |
| 1798 // Emit code to evaluate all the non-constant subexpressions and to store | 1798 // Emit code to evaluate all the non-constant subexpressions and to store |
| 1799 // them into the newly cloned array. | 1799 // them into the newly cloned array. |
| 1800 for (int i = 0; i < length; i++) { | 1800 for (int i = 0; i < length; i++) { |
| (...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2142 | 2142 |
| 2143 void FullCodeGenerator::EmitCallStoreContextSlot( | 2143 void FullCodeGenerator::EmitCallStoreContextSlot( |
| 2144 Handle<String> name, StrictMode strict_mode) { | 2144 Handle<String> name, StrictMode strict_mode) { |
| 2145 __ Mov(x11, Operand(name)); | 2145 __ Mov(x11, Operand(name)); |
| 2146 __ Mov(x10, Smi::FromInt(strict_mode)); | 2146 __ Mov(x10, Smi::FromInt(strict_mode)); |
| 2147 // jssp[0] : mode. | 2147 // jssp[0] : mode. |
| 2148 // jssp[8] : name. | 2148 // jssp[8] : name. |
| 2149 // jssp[16] : context. | 2149 // jssp[16] : context. |
| 2150 // jssp[24] : value. | 2150 // jssp[24] : value. |
| 2151 __ Push(x0, cp, x11, x10); | 2151 __ Push(x0, cp, x11, x10); |
| 2152 __ CallRuntime(Runtime::kHiddenStoreContextSlot, 4); | 2152 __ CallRuntime(Runtime::kStoreContextSlot, 4); |
| 2153 } | 2153 } |
| 2154 | 2154 |
| 2155 | 2155 |
| 2156 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 2156 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
| 2157 Token::Value op) { | 2157 Token::Value op) { |
| 2158 ASM_LOCATION("FullCodeGenerator::EmitVariableAssignment"); | 2158 ASM_LOCATION("FullCodeGenerator::EmitVariableAssignment"); |
| 2159 if (var->IsUnallocated()) { | 2159 if (var->IsUnallocated()) { |
| 2160 // Global var, const, or let. | 2160 // Global var, const, or let. |
| 2161 __ Mov(x2, Operand(var->name())); | 2161 __ Mov(x2, Operand(var->name())); |
| 2162 __ Ldr(x1, GlobalObjectMemOperand()); | 2162 __ Ldr(x1, GlobalObjectMemOperand()); |
| 2163 CallStoreIC(); | 2163 CallStoreIC(); |
| 2164 | 2164 |
| 2165 } else if (op == Token::INIT_CONST_LEGACY) { | 2165 } else if (op == Token::INIT_CONST_LEGACY) { |
| 2166 // Const initializers need a write barrier. | 2166 // Const initializers need a write barrier. |
| 2167 ASSERT(!var->IsParameter()); // No const parameters. | 2167 ASSERT(!var->IsParameter()); // No const parameters. |
| 2168 if (var->IsLookupSlot()) { | 2168 if (var->IsLookupSlot()) { |
| 2169 __ Push(x0); | 2169 __ Push(x0); |
| 2170 __ Mov(x0, Operand(var->name())); | 2170 __ Mov(x0, Operand(var->name())); |
| 2171 __ Push(cp, x0); // Context and name. | 2171 __ Push(cp, x0); // Context and name. |
| 2172 __ CallRuntime(Runtime::kHiddenInitializeConstContextSlot, 3); | 2172 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
| 2173 } else { | 2173 } else { |
| 2174 ASSERT(var->IsStackLocal() || var->IsContextSlot()); | 2174 ASSERT(var->IsStackLocal() || var->IsContextSlot()); |
| 2175 Label skip; | 2175 Label skip; |
| 2176 MemOperand location = VarOperand(var, x1); | 2176 MemOperand location = VarOperand(var, x1); |
| 2177 __ Ldr(x10, location); | 2177 __ Ldr(x10, location); |
| 2178 __ JumpIfNotRoot(x10, Heap::kTheHoleValueRootIndex, &skip); | 2178 __ JumpIfNotRoot(x10, Heap::kTheHoleValueRootIndex, &skip); |
| 2179 EmitStoreToStackLocalOrContextSlot(var, location); | 2179 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2180 __ Bind(&skip); | 2180 __ Bind(&skip); |
| 2181 } | 2181 } |
| 2182 | 2182 |
| 2183 } else if (var->mode() == LET && op != Token::INIT_LET) { | 2183 } else if (var->mode() == LET && op != Token::INIT_LET) { |
| 2184 // Non-initializing assignment to let variable needs a write barrier. | 2184 // Non-initializing assignment to let variable needs a write barrier. |
| 2185 if (var->IsLookupSlot()) { | 2185 if (var->IsLookupSlot()) { |
| 2186 EmitCallStoreContextSlot(var->name(), strict_mode()); | 2186 EmitCallStoreContextSlot(var->name(), strict_mode()); |
| 2187 } else { | 2187 } else { |
| 2188 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 2188 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); |
| 2189 Label assign; | 2189 Label assign; |
| 2190 MemOperand location = VarOperand(var, x1); | 2190 MemOperand location = VarOperand(var, x1); |
| 2191 __ Ldr(x10, location); | 2191 __ Ldr(x10, location); |
| 2192 __ JumpIfNotRoot(x10, Heap::kTheHoleValueRootIndex, &assign); | 2192 __ JumpIfNotRoot(x10, Heap::kTheHoleValueRootIndex, &assign); |
| 2193 __ Mov(x10, Operand(var->name())); | 2193 __ Mov(x10, Operand(var->name())); |
| 2194 __ Push(x10); | 2194 __ Push(x10); |
| 2195 __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1); | 2195 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 2196 // Perform the assignment. | 2196 // Perform the assignment. |
| 2197 __ Bind(&assign); | 2197 __ Bind(&assign); |
| 2198 EmitStoreToStackLocalOrContextSlot(var, location); | 2198 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2199 } | 2199 } |
| 2200 | 2200 |
| 2201 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { | 2201 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { |
| 2202 // Assignment to var or initializing assignment to let/const | 2202 // Assignment to var or initializing assignment to let/const |
| 2203 // in harmony mode. | 2203 // in harmony mode. |
| 2204 if (var->IsLookupSlot()) { | 2204 if (var->IsLookupSlot()) { |
| 2205 EmitCallStoreContextSlot(var->name(), strict_mode()); | 2205 EmitCallStoreContextSlot(var->name(), strict_mode()); |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2384 | 2384 |
| 2385 // Prepare to push the language mode. | 2385 // Prepare to push the language mode. |
| 2386 __ Mov(x10, Smi::FromInt(strict_mode())); | 2386 __ Mov(x10, Smi::FromInt(strict_mode())); |
| 2387 // Prepare to push the start position of the scope the calls resides in. | 2387 // Prepare to push the start position of the scope the calls resides in. |
| 2388 __ Mov(x11, Smi::FromInt(scope()->start_position())); | 2388 __ Mov(x11, Smi::FromInt(scope()->start_position())); |
| 2389 | 2389 |
| 2390 // Push. | 2390 // Push. |
| 2391 __ Push(x10, x11); | 2391 __ Push(x10, x11); |
| 2392 | 2392 |
| 2393 // Do the runtime call. | 2393 // Do the runtime call. |
| 2394 __ CallRuntime(Runtime::kHiddenResolvePossiblyDirectEval, 5); | 2394 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); |
| 2395 } | 2395 } |
| 2396 | 2396 |
| 2397 | 2397 |
| 2398 void FullCodeGenerator::VisitCall(Call* expr) { | 2398 void FullCodeGenerator::VisitCall(Call* expr) { |
| 2399 #ifdef DEBUG | 2399 #ifdef DEBUG |
| 2400 // We want to verify that RecordJSReturnSite gets called on all paths | 2400 // We want to verify that RecordJSReturnSite gets called on all paths |
| 2401 // through this function. Avoid early returns. | 2401 // through this function. Avoid early returns. |
| 2402 expr->return_is_recorded_ = false; | 2402 expr->return_is_recorded_ = false; |
| 2403 #endif | 2403 #endif |
| 2404 | 2404 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2461 // by eval-introduced variables. | 2461 // by eval-introduced variables. |
| 2462 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); | 2462 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); |
| 2463 } | 2463 } |
| 2464 | 2464 |
| 2465 __ Bind(&slow); | 2465 __ Bind(&slow); |
| 2466 // Call the runtime to find the function to call (returned in x0) | 2466 // Call the runtime to find the function to call (returned in x0) |
| 2467 // and the object holding it (returned in x1). | 2467 // and the object holding it (returned in x1). |
| 2468 __ Push(context_register()); | 2468 __ Push(context_register()); |
| 2469 __ Mov(x10, Operand(proxy->name())); | 2469 __ Mov(x10, Operand(proxy->name())); |
| 2470 __ Push(x10); | 2470 __ Push(x10); |
| 2471 __ CallRuntime(Runtime::kHiddenLoadContextSlot, 2); | 2471 __ CallRuntime(Runtime::kLoadContextSlot, 2); |
| 2472 __ Push(x0, x1); // Receiver, function. | 2472 __ Push(x0, x1); // Receiver, function. |
| 2473 | 2473 |
| 2474 // If fast case code has been generated, emit code to push the | 2474 // If fast case code has been generated, emit code to push the |
| 2475 // function and receiver and have the slow path jump around this | 2475 // function and receiver and have the slow path jump around this |
| 2476 // code. | 2476 // code. |
| 2477 if (done.is_linked()) { | 2477 if (done.is_linked()) { |
| 2478 Label call; | 2478 Label call; |
| 2479 __ B(&call); | 2479 __ B(&call); |
| 2480 __ Bind(&done); | 2480 __ Bind(&done); |
| 2481 // Push function. | 2481 // Push function. |
| (...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3109 __ B(&done); | 3109 __ B(&done); |
| 3110 } | 3110 } |
| 3111 | 3111 |
| 3112 __ Bind(&runtime); | 3112 __ Bind(&runtime); |
| 3113 __ Mov(x1, index); | 3113 __ Mov(x1, index); |
| 3114 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); | 3114 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); |
| 3115 __ B(&done); | 3115 __ B(&done); |
| 3116 } | 3116 } |
| 3117 | 3117 |
| 3118 __ Bind(¬_date_object); | 3118 __ Bind(¬_date_object); |
| 3119 __ CallRuntime(Runtime::kHiddenThrowNotDateError, 0); | 3119 __ CallRuntime(Runtime::kThrowNotDateError, 0); |
| 3120 __ Bind(&done); | 3120 __ Bind(&done); |
| 3121 context()->Plug(x0); | 3121 context()->Plug(x0); |
| 3122 } | 3122 } |
| 3123 | 3123 |
| 3124 | 3124 |
| 3125 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { | 3125 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { |
| 3126 ZoneList<Expression*>* args = expr->arguments(); | 3126 ZoneList<Expression*>* args = expr->arguments(); |
| 3127 ASSERT_EQ(3, args->length()); | 3127 ASSERT_EQ(3, args->length()); |
| 3128 | 3128 |
| 3129 Register string = x0; | 3129 Register string = x0; |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3456 | 3456 |
| 3457 // Load the key and data from the cache. | 3457 // Load the key and data from the cache. |
| 3458 __ Ldp(x2, x3, MemOperand(x3)); | 3458 __ Ldp(x2, x3, MemOperand(x3)); |
| 3459 | 3459 |
| 3460 __ Cmp(key, x2); | 3460 __ Cmp(key, x2); |
| 3461 __ CmovX(x0, x3, eq); | 3461 __ CmovX(x0, x3, eq); |
| 3462 __ B(eq, &done); | 3462 __ B(eq, &done); |
| 3463 | 3463 |
| 3464 // Call runtime to perform the lookup. | 3464 // Call runtime to perform the lookup. |
| 3465 __ Push(cache, key); | 3465 __ Push(cache, key); |
| 3466 __ CallRuntime(Runtime::kHiddenGetFromCache, 2); | 3466 __ CallRuntime(Runtime::kGetFromCache, 2); |
| 3467 | 3467 |
| 3468 __ Bind(&done); | 3468 __ Bind(&done); |
| 3469 context()->Plug(x0); | 3469 context()->Plug(x0); |
| 3470 } | 3470 } |
| 3471 | 3471 |
| 3472 | 3472 |
| 3473 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { | 3473 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { |
| 3474 ZoneList<Expression*>* args = expr->arguments(); | 3474 ZoneList<Expression*>* args = expr->arguments(); |
| 3475 VisitForAccumulatorValue(args->at(0)); | 3475 VisitForAccumulatorValue(args->at(0)); |
| 3476 | 3476 |
| (...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3814 context()->Plug(x0); | 3814 context()->Plug(x0); |
| 3815 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 3815 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
| 3816 // Result of deleting non-global, non-dynamic variables is false. | 3816 // Result of deleting non-global, non-dynamic variables is false. |
| 3817 // The subexpression does not have side effects. | 3817 // The subexpression does not have side effects. |
| 3818 context()->Plug(var->is_this()); | 3818 context()->Plug(var->is_this()); |
| 3819 } else { | 3819 } else { |
| 3820 // Non-global variable. Call the runtime to try to delete from the | 3820 // Non-global variable. Call the runtime to try to delete from the |
| 3821 // context where the variable was introduced. | 3821 // context where the variable was introduced. |
| 3822 __ Mov(x2, Operand(var->name())); | 3822 __ Mov(x2, Operand(var->name())); |
| 3823 __ Push(context_register(), x2); | 3823 __ Push(context_register(), x2); |
| 3824 __ CallRuntime(Runtime::kHiddenDeleteContextSlot, 2); | 3824 __ CallRuntime(Runtime::kDeleteContextSlot, 2); |
| 3825 context()->Plug(x0); | 3825 context()->Plug(x0); |
| 3826 } | 3826 } |
| 3827 } else { | 3827 } else { |
| 3828 // Result of deleting non-property, non-variable reference is true. | 3828 // Result of deleting non-property, non-variable reference is true. |
| 3829 // The subexpression may have side effects. | 3829 // The subexpression may have side effects. |
| 3830 VisitForEffect(expr->expression()); | 3830 VisitForEffect(expr->expression()); |
| 3831 context()->Plug(true); | 3831 context()->Plug(true); |
| 3832 } | 3832 } |
| 3833 break; | 3833 break; |
| 3834 break; | 3834 break; |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4094 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { | 4094 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { |
| 4095 Label done, slow; | 4095 Label done, slow; |
| 4096 | 4096 |
| 4097 // Generate code for loading from variables potentially shadowed | 4097 // Generate code for loading from variables potentially shadowed |
| 4098 // by eval-introduced variables. | 4098 // by eval-introduced variables. |
| 4099 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); | 4099 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); |
| 4100 | 4100 |
| 4101 __ Bind(&slow); | 4101 __ Bind(&slow); |
| 4102 __ Mov(x0, Operand(proxy->name())); | 4102 __ Mov(x0, Operand(proxy->name())); |
| 4103 __ Push(cp, x0); | 4103 __ Push(cp, x0); |
| 4104 __ CallRuntime(Runtime::kHiddenLoadContextSlotNoReferenceError, 2); | 4104 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); |
| 4105 PrepareForBailout(expr, TOS_REG); | 4105 PrepareForBailout(expr, TOS_REG); |
| 4106 __ Bind(&done); | 4106 __ Bind(&done); |
| 4107 | 4107 |
| 4108 context()->Plug(x0); | 4108 context()->Plug(x0); |
| 4109 } else { | 4109 } else { |
| 4110 // This expression cannot throw a reference error at the top level. | 4110 // This expression cannot throw a reference error at the top level. |
| 4111 VisitInDuplicateContext(expr); | 4111 VisitInDuplicateContext(expr); |
| 4112 } | 4112 } |
| 4113 } | 4113 } |
| 4114 | 4114 |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4346 __ Mov(x1, Smi::FromInt(continuation.pos())); | 4346 __ Mov(x1, Smi::FromInt(continuation.pos())); |
| 4347 __ Str(x1, FieldMemOperand(x0, JSGeneratorObject::kContinuationOffset)); | 4347 __ Str(x1, FieldMemOperand(x0, JSGeneratorObject::kContinuationOffset)); |
| 4348 __ Str(cp, FieldMemOperand(x0, JSGeneratorObject::kContextOffset)); | 4348 __ Str(cp, FieldMemOperand(x0, JSGeneratorObject::kContextOffset)); |
| 4349 __ Mov(x1, cp); | 4349 __ Mov(x1, cp); |
| 4350 __ RecordWriteField(x0, JSGeneratorObject::kContextOffset, x1, x2, | 4350 __ RecordWriteField(x0, JSGeneratorObject::kContextOffset, x1, x2, |
| 4351 kLRHasBeenSaved, kDontSaveFPRegs); | 4351 kLRHasBeenSaved, kDontSaveFPRegs); |
| 4352 __ Add(x1, fp, StandardFrameConstants::kExpressionsOffset); | 4352 __ Add(x1, fp, StandardFrameConstants::kExpressionsOffset); |
| 4353 __ Cmp(__ StackPointer(), x1); | 4353 __ Cmp(__ StackPointer(), x1); |
| 4354 __ B(eq, &post_runtime); | 4354 __ B(eq, &post_runtime); |
| 4355 __ Push(x0); // generator object | 4355 __ Push(x0); // generator object |
| 4356 __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1); | 4356 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
| 4357 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4357 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 4358 __ Bind(&post_runtime); | 4358 __ Bind(&post_runtime); |
| 4359 __ Pop(result_register()); | 4359 __ Pop(result_register()); |
| 4360 EmitReturnSequence(); | 4360 EmitReturnSequence(); |
| 4361 | 4361 |
| 4362 __ Bind(&resume); | 4362 __ Bind(&resume); |
| 4363 context()->Plug(result_register()); | 4363 context()->Plug(result_register()); |
| 4364 break; | 4364 break; |
| 4365 } | 4365 } |
| 4366 | 4366 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4417 const int generator_object_depth = kPointerSize + handler_size; | 4417 const int generator_object_depth = kPointerSize + handler_size; |
| 4418 __ Peek(x0, generator_object_depth); | 4418 __ Peek(x0, generator_object_depth); |
| 4419 __ Push(x0); // g | 4419 __ Push(x0); // g |
| 4420 ASSERT((l_continuation.pos() > 0) && Smi::IsValid(l_continuation.pos())); | 4420 ASSERT((l_continuation.pos() > 0) && Smi::IsValid(l_continuation.pos())); |
| 4421 __ Mov(x1, Smi::FromInt(l_continuation.pos())); | 4421 __ Mov(x1, Smi::FromInt(l_continuation.pos())); |
| 4422 __ Str(x1, FieldMemOperand(x0, JSGeneratorObject::kContinuationOffset)); | 4422 __ Str(x1, FieldMemOperand(x0, JSGeneratorObject::kContinuationOffset)); |
| 4423 __ Str(cp, FieldMemOperand(x0, JSGeneratorObject::kContextOffset)); | 4423 __ Str(cp, FieldMemOperand(x0, JSGeneratorObject::kContextOffset)); |
| 4424 __ Mov(x1, cp); | 4424 __ Mov(x1, cp); |
| 4425 __ RecordWriteField(x0, JSGeneratorObject::kContextOffset, x1, x2, | 4425 __ RecordWriteField(x0, JSGeneratorObject::kContextOffset, x1, x2, |
| 4426 kLRHasBeenSaved, kDontSaveFPRegs); | 4426 kLRHasBeenSaved, kDontSaveFPRegs); |
| 4427 __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1); | 4427 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
| 4428 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4428 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 4429 __ Pop(x0); // result | 4429 __ Pop(x0); // result |
| 4430 EmitReturnSequence(); | 4430 EmitReturnSequence(); |
| 4431 __ Bind(&l_resume); // received in x0 | 4431 __ Bind(&l_resume); // received in x0 |
| 4432 __ PopTryHandler(); | 4432 __ PopTryHandler(); |
| 4433 | 4433 |
| 4434 // receiver = iter; f = 'next'; arg = received; | 4434 // receiver = iter; f = 'next'; arg = received; |
| 4435 __ Bind(&l_next); | 4435 __ Bind(&l_next); |
| 4436 __ LoadRoot(x2, Heap::knext_stringRootIndex); // "next" | 4436 __ LoadRoot(x2, Heap::knext_stringRootIndex); // "next" |
| 4437 __ Peek(x3, 1 * kPointerSize); // iter | 4437 __ Peek(x3, 1 * kPointerSize); // iter |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4476 Expression *value, | 4476 Expression *value, |
| 4477 JSGeneratorObject::ResumeMode resume_mode) { | 4477 JSGeneratorObject::ResumeMode resume_mode) { |
| 4478 ASM_LOCATION("FullCodeGenerator::EmitGeneratorResume"); | 4478 ASM_LOCATION("FullCodeGenerator::EmitGeneratorResume"); |
| 4479 Register value_reg = x0; | 4479 Register value_reg = x0; |
| 4480 Register generator_object = x1; | 4480 Register generator_object = x1; |
| 4481 Register the_hole = x2; | 4481 Register the_hole = x2; |
| 4482 Register operand_stack_size = w3; | 4482 Register operand_stack_size = w3; |
| 4483 Register function = x4; | 4483 Register function = x4; |
| 4484 | 4484 |
| 4485 // The value stays in x0, and is ultimately read by the resumed generator, as | 4485 // The value stays in x0, and is ultimately read by the resumed generator, as |
| 4486 // if CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject) returned it. Or it | 4486 // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it |
| 4487 // is read to throw the value when the resumed generator is already closed. r1 | 4487 // is read to throw the value when the resumed generator is already closed. r1 |
| 4488 // will hold the generator object until the activation has been resumed. | 4488 // will hold the generator object until the activation has been resumed. |
| 4489 VisitForStackValue(generator); | 4489 VisitForStackValue(generator); |
| 4490 VisitForAccumulatorValue(value); | 4490 VisitForAccumulatorValue(value); |
| 4491 __ Pop(generator_object); | 4491 __ Pop(generator_object); |
| 4492 | 4492 |
| 4493 // Check generator state. | 4493 // Check generator state. |
| 4494 Label wrong_state, closed_state, done; | 4494 Label wrong_state, closed_state, done; |
| 4495 __ Ldr(x10, FieldMemOperand(generator_object, | 4495 __ Ldr(x10, FieldMemOperand(generator_object, |
| 4496 JSGeneratorObject::kContinuationOffset)); | 4496 JSGeneratorObject::kContinuationOffset)); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4558 | 4558 |
| 4559 __ Bind(&slow_resume); | 4559 __ Bind(&slow_resume); |
| 4560 } | 4560 } |
| 4561 | 4561 |
| 4562 // Otherwise, we push holes for the operand stack and call the runtime to fix | 4562 // Otherwise, we push holes for the operand stack and call the runtime to fix |
| 4563 // up the stack and the handlers. | 4563 // up the stack and the handlers. |
| 4564 __ PushMultipleTimes(the_hole, operand_stack_size); | 4564 __ PushMultipleTimes(the_hole, operand_stack_size); |
| 4565 | 4565 |
| 4566 __ Mov(x10, Smi::FromInt(resume_mode)); | 4566 __ Mov(x10, Smi::FromInt(resume_mode)); |
| 4567 __ Push(generator_object, result_register(), x10); | 4567 __ Push(generator_object, result_register(), x10); |
| 4568 __ CallRuntime(Runtime::kHiddenResumeJSGeneratorObject, 3); | 4568 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); |
| 4569 // Not reached: the runtime call returns elsewhere. | 4569 // Not reached: the runtime call returns elsewhere. |
| 4570 __ Unreachable(); | 4570 __ Unreachable(); |
| 4571 | 4571 |
| 4572 // Reach here when generator is closed. | 4572 // Reach here when generator is closed. |
| 4573 __ Bind(&closed_state); | 4573 __ Bind(&closed_state); |
| 4574 if (resume_mode == JSGeneratorObject::NEXT) { | 4574 if (resume_mode == JSGeneratorObject::NEXT) { |
| 4575 // Return completed iterator result when generator is closed. | 4575 // Return completed iterator result when generator is closed. |
| 4576 __ LoadRoot(x10, Heap::kUndefinedValueRootIndex); | 4576 __ LoadRoot(x10, Heap::kUndefinedValueRootIndex); |
| 4577 __ Push(x10); | 4577 __ Push(x10); |
| 4578 // Pop value from top-of-stack slot; box result into result register. | 4578 // Pop value from top-of-stack slot; box result into result register. |
| 4579 EmitCreateIteratorResult(true); | 4579 EmitCreateIteratorResult(true); |
| 4580 } else { | 4580 } else { |
| 4581 // Throw the provided value. | 4581 // Throw the provided value. |
| 4582 __ Push(value_reg); | 4582 __ Push(value_reg); |
| 4583 __ CallRuntime(Runtime::kHiddenThrow, 1); | 4583 __ CallRuntime(Runtime::kThrow, 1); |
| 4584 } | 4584 } |
| 4585 __ B(&done); | 4585 __ B(&done); |
| 4586 | 4586 |
| 4587 // Throw error if we attempt to operate on a running generator. | 4587 // Throw error if we attempt to operate on a running generator. |
| 4588 __ Bind(&wrong_state); | 4588 __ Bind(&wrong_state); |
| 4589 __ Push(generator_object); | 4589 __ Push(generator_object); |
| 4590 __ CallRuntime(Runtime::kHiddenThrowGeneratorStateError, 1); | 4590 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); |
| 4591 | 4591 |
| 4592 __ Bind(&done); | 4592 __ Bind(&done); |
| 4593 context()->Plug(result_register()); | 4593 context()->Plug(result_register()); |
| 4594 } | 4594 } |
| 4595 | 4595 |
| 4596 | 4596 |
| 4597 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { | 4597 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { |
| 4598 Label gc_required; | 4598 Label gc_required; |
| 4599 Label allocated; | 4599 Label allocated; |
| 4600 | 4600 |
| 4601 Handle<Map> map(isolate()->native_context()->iterator_result_map()); | 4601 Handle<Map> map(isolate()->native_context()->iterator_result_map()); |
| 4602 | 4602 |
| 4603 // Allocate and populate an object with this form: { value: VAL, done: DONE } | 4603 // Allocate and populate an object with this form: { value: VAL, done: DONE } |
| 4604 | 4604 |
| 4605 Register result = x0; | 4605 Register result = x0; |
| 4606 __ Allocate(map->instance_size(), result, x10, x11, &gc_required, TAG_OBJECT); | 4606 __ Allocate(map->instance_size(), result, x10, x11, &gc_required, TAG_OBJECT); |
| 4607 __ B(&allocated); | 4607 __ B(&allocated); |
| 4608 | 4608 |
| 4609 __ Bind(&gc_required); | 4609 __ Bind(&gc_required); |
| 4610 __ Push(Smi::FromInt(map->instance_size())); | 4610 __ Push(Smi::FromInt(map->instance_size())); |
| 4611 __ CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1); | 4611 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
| 4612 __ Ldr(context_register(), | 4612 __ Ldr(context_register(), |
| 4613 MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4613 MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 4614 | 4614 |
| 4615 __ Bind(&allocated); | 4615 __ Bind(&allocated); |
| 4616 Register map_reg = x1; | 4616 Register map_reg = x1; |
| 4617 Register result_value = x2; | 4617 Register result_value = x2; |
| 4618 Register boolean_done = x3; | 4618 Register boolean_done = x3; |
| 4619 Register empty_fixed_array = x4; | 4619 Register empty_fixed_array = x4; |
| 4620 Register untagged_result = x5; | 4620 Register untagged_result = x5; |
| 4621 __ Mov(map_reg, Operand(map)); | 4621 __ Mov(map_reg, Operand(map)); |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4886 return previous_; | 4886 return previous_; |
| 4887 } | 4887 } |
| 4888 | 4888 |
| 4889 | 4889 |
| 4890 #undef __ | 4890 #undef __ |
| 4891 | 4891 |
| 4892 | 4892 |
| 4893 } } // namespace v8::internal | 4893 } } // namespace v8::internal |
| 4894 | 4894 |
| 4895 #endif // V8_TARGET_ARCH_ARM64 | 4895 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |