| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 | 228 |
| 229 bool function_in_register_x1 = true; | 229 bool function_in_register_x1 = true; |
| 230 | 230 |
| 231 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 231 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 232 if (heap_slots > 0) { | 232 if (heap_slots > 0) { |
| 233 // Argument to NewContext is the function, which is still in x1. | 233 // Argument to NewContext is the function, which is still in x1. |
| 234 Comment cmnt(masm_, "[ Allocate context"); | 234 Comment cmnt(masm_, "[ Allocate context"); |
| 235 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) { | 235 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) { |
| 236 __ Mov(x10, Operand(info->scope()->GetScopeInfo())); | 236 __ Mov(x10, Operand(info->scope()->GetScopeInfo())); |
| 237 __ Push(x1, x10); | 237 __ Push(x1, x10); |
| 238 __ CallRuntime(Runtime::kNewGlobalContext, 2); | 238 __ CallRuntime(Runtime::kHiddenNewGlobalContext, 2); |
| 239 } else if (heap_slots <= FastNewContextStub::kMaximumSlots) { | 239 } else if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
| 240 FastNewContextStub stub(heap_slots); | 240 FastNewContextStub stub(heap_slots); |
| 241 __ CallStub(&stub); | 241 __ CallStub(&stub); |
| 242 } else { | 242 } else { |
| 243 __ Push(x1); | 243 __ Push(x1); |
| 244 __ CallRuntime(Runtime::kNewFunctionContext, 1); | 244 __ CallRuntime(Runtime::kHiddenNewFunctionContext, 1); |
| 245 } | 245 } |
| 246 function_in_register_x1 = false; | 246 function_in_register_x1 = false; |
| 247 // Context is returned in x0. It replaces the context passed to us. | 247 // Context is returned in x0. It replaces the context passed to us. |
| 248 // It's saved in the stack and kept live in cp. | 248 // It's saved in the stack and kept live in cp. |
| 249 __ Mov(cp, x0); | 249 __ Mov(cp, x0); |
| 250 __ Str(x0, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 250 __ Str(x0, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 251 // Copy any necessary parameters into the context. | 251 // Copy any necessary parameters into the context. |
| 252 int num_parameters = info->scope()->num_parameters(); | 252 int num_parameters = info->scope()->num_parameters(); |
| 253 for (int i = 0; i < num_parameters; i++) { | 253 for (int i = 0; i < num_parameters; i++) { |
| 254 Variable* var = scope()->parameter(i); | 254 Variable* var = scope()->parameter(i); |
| (...skipping 613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 868 // Note: For variables we must not push an initial value (such as | 868 // Note: For variables we must not push an initial value (such as |
| 869 // 'undefined') because we may have a (legal) redeclaration and we | 869 // 'undefined') because we may have a (legal) redeclaration and we |
| 870 // must not destroy the current value. | 870 // must not destroy the current value. |
| 871 if (hole_init) { | 871 if (hole_init) { |
| 872 __ LoadRoot(x0, Heap::kTheHoleValueRootIndex); | 872 __ LoadRoot(x0, Heap::kTheHoleValueRootIndex); |
| 873 __ Push(cp, x2, x1, x0); | 873 __ Push(cp, x2, x1, x0); |
| 874 } else { | 874 } else { |
| 875 // Pushing 0 (xzr) indicates no initial value. | 875 // Pushing 0 (xzr) indicates no initial value. |
| 876 __ Push(cp, x2, x1, xzr); | 876 __ Push(cp, x2, x1, xzr); |
| 877 } | 877 } |
| 878 __ CallRuntime(Runtime::kDeclareContextSlot, 4); | 878 __ CallRuntime(Runtime::kHiddenDeclareContextSlot, 4); |
| 879 break; | 879 break; |
| 880 } | 880 } |
| 881 } | 881 } |
| 882 } | 882 } |
| 883 | 883 |
| 884 | 884 |
| 885 void FullCodeGenerator::VisitFunctionDeclaration( | 885 void FullCodeGenerator::VisitFunctionDeclaration( |
| 886 FunctionDeclaration* declaration) { | 886 FunctionDeclaration* declaration) { |
| 887 VariableProxy* proxy = declaration->proxy(); | 887 VariableProxy* proxy = declaration->proxy(); |
| 888 Variable* variable = proxy->var(); | 888 Variable* variable = proxy->var(); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 924 break; | 924 break; |
| 925 } | 925 } |
| 926 | 926 |
| 927 case Variable::LOOKUP: { | 927 case Variable::LOOKUP: { |
| 928 Comment cmnt(masm_, "[ Function Declaration"); | 928 Comment cmnt(masm_, "[ Function Declaration"); |
| 929 __ Mov(x2, Operand(variable->name())); | 929 __ Mov(x2, Operand(variable->name())); |
| 930 __ Mov(x1, Smi::FromInt(NONE)); | 930 __ Mov(x1, Smi::FromInt(NONE)); |
| 931 __ Push(cp, x2, x1); | 931 __ Push(cp, x2, x1); |
| 932 // Push initial value for function declaration. | 932 // Push initial value for function declaration. |
| 933 VisitForStackValue(declaration->fun()); | 933 VisitForStackValue(declaration->fun()); |
| 934 __ CallRuntime(Runtime::kDeclareContextSlot, 4); | 934 __ CallRuntime(Runtime::kHiddenDeclareContextSlot, 4); |
| 935 break; | 935 break; |
| 936 } | 936 } |
| 937 } | 937 } |
| 938 } | 938 } |
| 939 | 939 |
| 940 | 940 |
| 941 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { | 941 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { |
| 942 Variable* variable = declaration->proxy()->var(); | 942 Variable* variable = declaration->proxy()->var(); |
| 943 ASSERT(variable->location() == Variable::CONTEXT); | 943 ASSERT(variable->location() == Variable::CONTEXT); |
| 944 ASSERT(variable->interface()->IsFrozen()); | 944 ASSERT(variable->interface()->IsFrozen()); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 999 | 999 |
| 1000 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 1000 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 1001 // Call the runtime to declare the globals. | 1001 // Call the runtime to declare the globals. |
| 1002 __ Mov(x11, Operand(pairs)); | 1002 __ Mov(x11, Operand(pairs)); |
| 1003 Register flags = xzr; | 1003 Register flags = xzr; |
| 1004 if (Smi::FromInt(DeclareGlobalsFlags())) { | 1004 if (Smi::FromInt(DeclareGlobalsFlags())) { |
| 1005 flags = x10; | 1005 flags = x10; |
| 1006 __ Mov(flags, Smi::FromInt(DeclareGlobalsFlags())); | 1006 __ Mov(flags, Smi::FromInt(DeclareGlobalsFlags())); |
| 1007 } | 1007 } |
| 1008 __ Push(cp, x11, flags); | 1008 __ Push(cp, x11, flags); |
| 1009 __ CallRuntime(Runtime::kDeclareGlobals, 3); | 1009 __ CallRuntime(Runtime::kHiddenDeclareGlobals, 3); |
| 1010 // Return value is ignored. | 1010 // Return value is ignored. |
| 1011 } | 1011 } |
| 1012 | 1012 |
| 1013 | 1013 |
| 1014 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { | 1014 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { |
| 1015 // Call the runtime to declare the modules. | 1015 // Call the runtime to declare the modules. |
| 1016 __ Push(descriptions); | 1016 __ Push(descriptions); |
| 1017 __ CallRuntime(Runtime::kDeclareModules, 1); | 1017 __ CallRuntime(Runtime::kHiddenDeclareModules, 1); |
| 1018 // Return value is ignored. | 1018 // Return value is ignored. |
| 1019 } | 1019 } |
| 1020 | 1020 |
| 1021 | 1021 |
| 1022 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 1022 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
| 1023 ASM_LOCATION("FullCodeGenerator::VisitSwitchStatement"); | 1023 ASM_LOCATION("FullCodeGenerator::VisitSwitchStatement"); |
| 1024 Comment cmnt(masm_, "[ SwitchStatement"); | 1024 Comment cmnt(masm_, "[ SwitchStatement"); |
| 1025 Breakable nested_statement(this, stmt); | 1025 Breakable nested_statement(this, stmt); |
| 1026 SetStatementPosition(stmt); | 1026 SetStatementPosition(stmt); |
| 1027 | 1027 |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1360 scope()->is_function_scope() && | 1360 scope()->is_function_scope() && |
| 1361 info->num_literals() == 0) { | 1361 info->num_literals() == 0) { |
| 1362 FastNewClosureStub stub(info->strict_mode(), info->is_generator()); | 1362 FastNewClosureStub stub(info->strict_mode(), info->is_generator()); |
| 1363 __ Mov(x2, Operand(info)); | 1363 __ Mov(x2, Operand(info)); |
| 1364 __ CallStub(&stub); | 1364 __ CallStub(&stub); |
| 1365 } else { | 1365 } else { |
| 1366 __ Mov(x11, Operand(info)); | 1366 __ Mov(x11, Operand(info)); |
| 1367 __ LoadRoot(x10, pretenure ? Heap::kTrueValueRootIndex | 1367 __ LoadRoot(x10, pretenure ? Heap::kTrueValueRootIndex |
| 1368 : Heap::kFalseValueRootIndex); | 1368 : Heap::kFalseValueRootIndex); |
| 1369 __ Push(cp, x11, x10); | 1369 __ Push(cp, x11, x10); |
| 1370 __ CallRuntime(Runtime::kNewClosure, 3); | 1370 __ CallRuntime(Runtime::kHiddenNewClosure, 3); |
| 1371 } | 1371 } |
| 1372 context()->Plug(x0); | 1372 context()->Plug(x0); |
| 1373 } | 1373 } |
| 1374 | 1374 |
| 1375 | 1375 |
| 1376 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 1376 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
| 1377 Comment cmnt(masm_, "[ VariableProxy"); | 1377 Comment cmnt(masm_, "[ VariableProxy"); |
| 1378 EmitVariableLoad(expr); | 1378 EmitVariableLoad(expr); |
| 1379 } | 1379 } |
| 1380 | 1380 |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1476 Variable* local = var->local_if_not_shadowed(); | 1476 Variable* local = var->local_if_not_shadowed(); |
| 1477 __ Ldr(x0, ContextSlotOperandCheckExtensions(local, slow)); | 1477 __ Ldr(x0, ContextSlotOperandCheckExtensions(local, slow)); |
| 1478 if (local->mode() == LET || local->mode() == CONST || | 1478 if (local->mode() == LET || local->mode() == CONST || |
| 1479 local->mode() == CONST_LEGACY) { | 1479 local->mode() == CONST_LEGACY) { |
| 1480 __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, done); | 1480 __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, done); |
| 1481 if (local->mode() == CONST_LEGACY) { | 1481 if (local->mode() == CONST_LEGACY) { |
| 1482 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); | 1482 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); |
| 1483 } else { // LET || CONST | 1483 } else { // LET || CONST |
| 1484 __ Mov(x0, Operand(var->name())); | 1484 __ Mov(x0, Operand(var->name())); |
| 1485 __ Push(x0); | 1485 __ Push(x0); |
| 1486 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1486 __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1); |
| 1487 } | 1487 } |
| 1488 } | 1488 } |
| 1489 __ B(done); | 1489 __ B(done); |
| 1490 } | 1490 } |
| 1491 } | 1491 } |
| 1492 | 1492 |
| 1493 | 1493 |
| 1494 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { | 1494 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { |
| 1495 // Record position before possible IC call. | 1495 // Record position before possible IC call. |
| 1496 SetSourcePosition(proxy->position()); | 1496 SetSourcePosition(proxy->position()); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1554 if (!skip_init_check) { | 1554 if (!skip_init_check) { |
| 1555 // Let and const need a read barrier. | 1555 // Let and const need a read barrier. |
| 1556 GetVar(x0, var); | 1556 GetVar(x0, var); |
| 1557 Label done; | 1557 Label done; |
| 1558 __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, &done); | 1558 __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, &done); |
| 1559 if (var->mode() == LET || var->mode() == CONST) { | 1559 if (var->mode() == LET || var->mode() == CONST) { |
| 1560 // Throw a reference error when using an uninitialized let/const | 1560 // Throw a reference error when using an uninitialized let/const |
| 1561 // binding in harmony mode. | 1561 // binding in harmony mode. |
| 1562 __ Mov(x0, Operand(var->name())); | 1562 __ Mov(x0, Operand(var->name())); |
| 1563 __ Push(x0); | 1563 __ Push(x0); |
| 1564 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1564 __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1); |
| 1565 __ Bind(&done); | 1565 __ Bind(&done); |
| 1566 } else { | 1566 } else { |
| 1567 // Uninitalized const bindings outside of harmony mode are unholed. | 1567 // Uninitalized const bindings outside of harmony mode are unholed. |
| 1568 ASSERT(var->mode() == CONST_LEGACY); | 1568 ASSERT(var->mode() == CONST_LEGACY); |
| 1569 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); | 1569 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); |
| 1570 __ Bind(&done); | 1570 __ Bind(&done); |
| 1571 } | 1571 } |
| 1572 context()->Plug(x0); | 1572 context()->Plug(x0); |
| 1573 break; | 1573 break; |
| 1574 } | 1574 } |
| 1575 } | 1575 } |
| 1576 context()->Plug(var); | 1576 context()->Plug(var); |
| 1577 break; | 1577 break; |
| 1578 } | 1578 } |
| 1579 | 1579 |
| 1580 case Variable::LOOKUP: { | 1580 case Variable::LOOKUP: { |
| 1581 Label done, slow; | 1581 Label done, slow; |
| 1582 // Generate code for loading from variables potentially shadowed by | 1582 // Generate code for loading from variables potentially shadowed by |
| 1583 // eval-introduced variables. | 1583 // eval-introduced variables. |
| 1584 EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done); | 1584 EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done); |
| 1585 __ Bind(&slow); | 1585 __ Bind(&slow); |
| 1586 Comment cmnt(masm_, "Lookup variable"); | 1586 Comment cmnt(masm_, "Lookup variable"); |
| 1587 __ Mov(x1, Operand(var->name())); | 1587 __ Mov(x1, Operand(var->name())); |
| 1588 __ Push(cp, x1); // Context and name. | 1588 __ Push(cp, x1); // Context and name. |
| 1589 __ CallRuntime(Runtime::kLoadContextSlot, 2); | 1589 __ CallRuntime(Runtime::kHiddenLoadContextSlot, 2); |
| 1590 __ Bind(&done); | 1590 __ Bind(&done); |
| 1591 context()->Plug(x0); | 1591 context()->Plug(x0); |
| 1592 break; | 1592 break; |
| 1593 } | 1593 } |
| 1594 } | 1594 } |
| 1595 } | 1595 } |
| 1596 | 1596 |
| 1597 | 1597 |
| 1598 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1598 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 1599 Comment cmnt(masm_, "[ RegExpLiteral"); | 1599 Comment cmnt(masm_, "[ RegExpLiteral"); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1611 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | 1611 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
| 1612 __ Ldr(x5, FieldMemOperand(x4, literal_offset)); | 1612 __ Ldr(x5, FieldMemOperand(x4, literal_offset)); |
| 1613 __ JumpIfNotRoot(x5, Heap::kUndefinedValueRootIndex, &materialized); | 1613 __ JumpIfNotRoot(x5, Heap::kUndefinedValueRootIndex, &materialized); |
| 1614 | 1614 |
| 1615 // Create regexp literal using runtime function. | 1615 // Create regexp literal using runtime function. |
| 1616 // Result will be in x0. | 1616 // Result will be in x0. |
| 1617 __ Mov(x3, Smi::FromInt(expr->literal_index())); | 1617 __ Mov(x3, Smi::FromInt(expr->literal_index())); |
| 1618 __ Mov(x2, Operand(expr->pattern())); | 1618 __ Mov(x2, Operand(expr->pattern())); |
| 1619 __ Mov(x1, Operand(expr->flags())); | 1619 __ Mov(x1, Operand(expr->flags())); |
| 1620 __ Push(x4, x3, x2, x1); | 1620 __ Push(x4, x3, x2, x1); |
| 1621 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | 1621 __ CallRuntime(Runtime::kHiddenMaterializeRegExpLiteral, 4); |
| 1622 __ Mov(x5, x0); | 1622 __ Mov(x5, x0); |
| 1623 | 1623 |
| 1624 __ Bind(&materialized); | 1624 __ Bind(&materialized); |
| 1625 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; | 1625 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; |
| 1626 Label allocated, runtime_allocate; | 1626 Label allocated, runtime_allocate; |
| 1627 __ Allocate(size, x0, x2, x3, &runtime_allocate, TAG_OBJECT); | 1627 __ Allocate(size, x0, x2, x3, &runtime_allocate, TAG_OBJECT); |
| 1628 __ B(&allocated); | 1628 __ B(&allocated); |
| 1629 | 1629 |
| 1630 __ Bind(&runtime_allocate); | 1630 __ Bind(&runtime_allocate); |
| 1631 __ Mov(x10, Smi::FromInt(size)); | 1631 __ Mov(x10, Smi::FromInt(size)); |
| 1632 __ Push(x5, x10); | 1632 __ Push(x5, x10); |
| 1633 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); | 1633 __ CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1); |
| 1634 __ Pop(x5); | 1634 __ Pop(x5); |
| 1635 | 1635 |
| 1636 __ Bind(&allocated); | 1636 __ Bind(&allocated); |
| 1637 // After this, registers are used as follows: | 1637 // After this, registers are used as follows: |
| 1638 // x0: Newly allocated regexp. | 1638 // x0: Newly allocated regexp. |
| 1639 // x5: Materialized regexp. | 1639 // x5: Materialized regexp. |
| 1640 // x10, x11, x12: temps. | 1640 // x10, x11, x12: temps. |
| 1641 __ CopyFields(x0, x5, CPURegList(x10, x11, x12), size / kPointerSize); | 1641 __ CopyFields(x0, x5, CPURegList(x10, x11, x12), size / kPointerSize); |
| 1642 context()->Plug(x0); | 1642 context()->Plug(x0); |
| 1643 } | 1643 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1669 ? ObjectLiteral::kHasFunction | 1669 ? ObjectLiteral::kHasFunction |
| 1670 : ObjectLiteral::kNoFlags; | 1670 : ObjectLiteral::kNoFlags; |
| 1671 __ Mov(x0, Smi::FromInt(flags)); | 1671 __ Mov(x0, Smi::FromInt(flags)); |
| 1672 int properties_count = constant_properties->length() / 2; | 1672 int properties_count = constant_properties->length() / 2; |
| 1673 const int max_cloned_properties = | 1673 const int max_cloned_properties = |
| 1674 FastCloneShallowObjectStub::kMaximumClonedProperties; | 1674 FastCloneShallowObjectStub::kMaximumClonedProperties; |
| 1675 if (expr->may_store_doubles() || expr->depth() > 1 || Serializer::enabled() || | 1675 if (expr->may_store_doubles() || expr->depth() > 1 || Serializer::enabled() || |
| 1676 flags != ObjectLiteral::kFastElements || | 1676 flags != ObjectLiteral::kFastElements || |
| 1677 properties_count > max_cloned_properties) { | 1677 properties_count > max_cloned_properties) { |
| 1678 __ Push(x3, x2, x1, x0); | 1678 __ Push(x3, x2, x1, x0); |
| 1679 __ CallRuntime(Runtime::kCreateObjectLiteral, 4); | 1679 __ CallRuntime(Runtime::kHiddenCreateObjectLiteral, 4); |
| 1680 } else { | 1680 } else { |
| 1681 FastCloneShallowObjectStub stub(properties_count); | 1681 FastCloneShallowObjectStub stub(properties_count); |
| 1682 __ CallStub(&stub); | 1682 __ CallStub(&stub); |
| 1683 } | 1683 } |
| 1684 | 1684 |
| 1685 // If result_saved is true the result is on top of the stack. If | 1685 // If result_saved is true the result is on top of the stack. If |
| 1686 // result_saved is false the result is in x0. | 1686 // result_saved is false the result is in x0. |
| 1687 bool result_saved = false; | 1687 bool result_saved = false; |
| 1688 | 1688 |
| 1689 // Mark all computed expressions that are bound to a key that | 1689 // Mark all computed expressions that are bound to a key that |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1819 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, | 1819 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, |
| 1820 allocation_site_mode, | 1820 allocation_site_mode, |
| 1821 length); | 1821 length); |
| 1822 __ CallStub(&stub); | 1822 __ CallStub(&stub); |
| 1823 __ IncrementCounter( | 1823 __ IncrementCounter( |
| 1824 isolate()->counters()->cow_arrays_created_stub(), 1, x10, x11); | 1824 isolate()->counters()->cow_arrays_created_stub(), 1, x10, x11); |
| 1825 } else if ((expr->depth() > 1) || Serializer::enabled() || | 1825 } else if ((expr->depth() > 1) || Serializer::enabled() || |
| 1826 length > FastCloneShallowArrayStub::kMaximumClonedLength) { | 1826 length > FastCloneShallowArrayStub::kMaximumClonedLength) { |
| 1827 __ Mov(x0, Smi::FromInt(flags)); | 1827 __ Mov(x0, Smi::FromInt(flags)); |
| 1828 __ Push(x3, x2, x1, x0); | 1828 __ Push(x3, x2, x1, x0); |
| 1829 __ CallRuntime(Runtime::kCreateArrayLiteral, 4); | 1829 __ CallRuntime(Runtime::kHiddenCreateArrayLiteral, 4); |
| 1830 } else { | 1830 } else { |
| 1831 ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) || | 1831 ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) || |
| 1832 FLAG_smi_only_arrays); | 1832 FLAG_smi_only_arrays); |
| 1833 FastCloneShallowArrayStub::Mode mode = | 1833 FastCloneShallowArrayStub::Mode mode = |
| 1834 FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS; | 1834 FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS; |
| 1835 | 1835 |
| 1836 if (has_fast_elements) { | 1836 if (has_fast_elements) { |
| 1837 mode = FastCloneShallowArrayStub::CLONE_ELEMENTS; | 1837 mode = FastCloneShallowArrayStub::CLONE_ELEMENTS; |
| 1838 } | 1838 } |
| 1839 | 1839 |
| (...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2190 | 2190 |
| 2191 void FullCodeGenerator::EmitCallStoreContextSlot( | 2191 void FullCodeGenerator::EmitCallStoreContextSlot( |
| 2192 Handle<String> name, StrictMode strict_mode) { | 2192 Handle<String> name, StrictMode strict_mode) { |
| 2193 __ Mov(x11, Operand(name)); | 2193 __ Mov(x11, Operand(name)); |
| 2194 __ Mov(x10, Smi::FromInt(strict_mode)); | 2194 __ Mov(x10, Smi::FromInt(strict_mode)); |
| 2195 // jssp[0] : mode. | 2195 // jssp[0] : mode. |
| 2196 // jssp[8] : name. | 2196 // jssp[8] : name. |
| 2197 // jssp[16] : context. | 2197 // jssp[16] : context. |
| 2198 // jssp[24] : value. | 2198 // jssp[24] : value. |
| 2199 __ Push(x0, cp, x11, x10); | 2199 __ Push(x0, cp, x11, x10); |
| 2200 __ CallRuntime(Runtime::kStoreContextSlot, 4); | 2200 __ CallRuntime(Runtime::kHiddenStoreContextSlot, 4); |
| 2201 } | 2201 } |
| 2202 | 2202 |
| 2203 | 2203 |
| 2204 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 2204 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
| 2205 Token::Value op) { | 2205 Token::Value op) { |
| 2206 ASM_LOCATION("FullCodeGenerator::EmitVariableAssignment"); | 2206 ASM_LOCATION("FullCodeGenerator::EmitVariableAssignment"); |
| 2207 if (var->IsUnallocated()) { | 2207 if (var->IsUnallocated()) { |
| 2208 // Global var, const, or let. | 2208 // Global var, const, or let. |
| 2209 __ Mov(x2, Operand(var->name())); | 2209 __ Mov(x2, Operand(var->name())); |
| 2210 __ Ldr(x1, GlobalObjectMemOperand()); | 2210 __ Ldr(x1, GlobalObjectMemOperand()); |
| 2211 CallStoreIC(); | 2211 CallStoreIC(); |
| 2212 | 2212 |
| 2213 } else if (op == Token::INIT_CONST_LEGACY) { | 2213 } else if (op == Token::INIT_CONST_LEGACY) { |
| 2214 // Const initializers need a write barrier. | 2214 // Const initializers need a write barrier. |
| 2215 ASSERT(!var->IsParameter()); // No const parameters. | 2215 ASSERT(!var->IsParameter()); // No const parameters. |
| 2216 if (var->IsLookupSlot()) { | 2216 if (var->IsLookupSlot()) { |
| 2217 __ Push(x0); | 2217 __ Push(x0); |
| 2218 __ Mov(x0, Operand(var->name())); | 2218 __ Mov(x0, Operand(var->name())); |
| 2219 __ Push(cp, x0); // Context and name. | 2219 __ Push(cp, x0); // Context and name. |
| 2220 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 2220 __ CallRuntime(Runtime::kHiddenInitializeConstContextSlot, 3); |
| 2221 } else { | 2221 } else { |
| 2222 ASSERT(var->IsStackLocal() || var->IsContextSlot()); | 2222 ASSERT(var->IsStackLocal() || var->IsContextSlot()); |
| 2223 Label skip; | 2223 Label skip; |
| 2224 MemOperand location = VarOperand(var, x1); | 2224 MemOperand location = VarOperand(var, x1); |
| 2225 __ Ldr(x10, location); | 2225 __ Ldr(x10, location); |
| 2226 __ JumpIfNotRoot(x10, Heap::kTheHoleValueRootIndex, &skip); | 2226 __ JumpIfNotRoot(x10, Heap::kTheHoleValueRootIndex, &skip); |
| 2227 EmitStoreToStackLocalOrContextSlot(var, location); | 2227 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2228 __ Bind(&skip); | 2228 __ Bind(&skip); |
| 2229 } | 2229 } |
| 2230 | 2230 |
| 2231 } else if (var->mode() == LET && op != Token::INIT_LET) { | 2231 } else if (var->mode() == LET && op != Token::INIT_LET) { |
| 2232 // Non-initializing assignment to let variable needs a write barrier. | 2232 // Non-initializing assignment to let variable needs a write barrier. |
| 2233 if (var->IsLookupSlot()) { | 2233 if (var->IsLookupSlot()) { |
| 2234 EmitCallStoreContextSlot(var->name(), strict_mode()); | 2234 EmitCallStoreContextSlot(var->name(), strict_mode()); |
| 2235 } else { | 2235 } else { |
| 2236 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 2236 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); |
| 2237 Label assign; | 2237 Label assign; |
| 2238 MemOperand location = VarOperand(var, x1); | 2238 MemOperand location = VarOperand(var, x1); |
| 2239 __ Ldr(x10, location); | 2239 __ Ldr(x10, location); |
| 2240 __ JumpIfNotRoot(x10, Heap::kTheHoleValueRootIndex, &assign); | 2240 __ JumpIfNotRoot(x10, Heap::kTheHoleValueRootIndex, &assign); |
| 2241 __ Mov(x10, Operand(var->name())); | 2241 __ Mov(x10, Operand(var->name())); |
| 2242 __ Push(x10); | 2242 __ Push(x10); |
| 2243 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2243 __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1); |
| 2244 // Perform the assignment. | 2244 // Perform the assignment. |
| 2245 __ Bind(&assign); | 2245 __ Bind(&assign); |
| 2246 EmitStoreToStackLocalOrContextSlot(var, location); | 2246 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2247 } | 2247 } |
| 2248 | 2248 |
| 2249 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { | 2249 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { |
| 2250 // Assignment to var or initializing assignment to let/const | 2250 // Assignment to var or initializing assignment to let/const |
| 2251 // in harmony mode. | 2251 // in harmony mode. |
| 2252 if (var->IsLookupSlot()) { | 2252 if (var->IsLookupSlot()) { |
| 2253 EmitCallStoreContextSlot(var->name(), strict_mode()); | 2253 EmitCallStoreContextSlot(var->name(), strict_mode()); |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2473 | 2473 |
| 2474 // Prepare to push the language mode. | 2474 // Prepare to push the language mode. |
| 2475 __ Mov(x10, Smi::FromInt(strict_mode())); | 2475 __ Mov(x10, Smi::FromInt(strict_mode())); |
| 2476 // Prepare to push the start position of the scope the calls resides in. | 2476 // Prepare to push the start position of the scope the calls resides in. |
| 2477 __ Mov(x11, Smi::FromInt(scope()->start_position())); | 2477 __ Mov(x11, Smi::FromInt(scope()->start_position())); |
| 2478 | 2478 |
| 2479 // Push. | 2479 // Push. |
| 2480 __ Push(x10, x11); | 2480 __ Push(x10, x11); |
| 2481 | 2481 |
| 2482 // Do the runtime call. | 2482 // Do the runtime call. |
| 2483 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); | 2483 __ CallRuntime(Runtime::kHiddenResolvePossiblyDirectEval, 5); |
| 2484 } | 2484 } |
| 2485 | 2485 |
| 2486 | 2486 |
| 2487 void FullCodeGenerator::VisitCall(Call* expr) { | 2487 void FullCodeGenerator::VisitCall(Call* expr) { |
| 2488 #ifdef DEBUG | 2488 #ifdef DEBUG |
| 2489 // We want to verify that RecordJSReturnSite gets called on all paths | 2489 // We want to verify that RecordJSReturnSite gets called on all paths |
| 2490 // through this function. Avoid early returns. | 2490 // through this function. Avoid early returns. |
| 2491 expr->return_is_recorded_ = false; | 2491 expr->return_is_recorded_ = false; |
| 2492 #endif | 2492 #endif |
| 2493 | 2493 |
| 2494 Comment cmnt(masm_, "[ Call"); | 2494 Comment cmnt(masm_, "[ Call"); |
| 2495 Expression* callee = expr->expression(); | 2495 Expression* callee = expr->expression(); |
| 2496 Call::CallType call_type = expr->GetCallType(isolate()); | 2496 Call::CallType call_type = expr->GetCallType(isolate()); |
| 2497 | 2497 |
| 2498 if (call_type == Call::POSSIBLY_EVAL_CALL) { | 2498 if (call_type == Call::POSSIBLY_EVAL_CALL) { |
| 2499 // In a call to eval, we first call %ResolvePossiblyDirectEval to | 2499 // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval |
| 2500 // resolve the function we need to call and the receiver of the | 2500 // to resolve the function we need to call and the receiver of the |
| 2501 // call. Then we call the resolved function using the given | 2501 // call. Then we call the resolved function using the given |
| 2502 // arguments. | 2502 // arguments. |
| 2503 ZoneList<Expression*>* args = expr->arguments(); | 2503 ZoneList<Expression*>* args = expr->arguments(); |
| 2504 int arg_count = args->length(); | 2504 int arg_count = args->length(); |
| 2505 | 2505 |
| 2506 { | 2506 { |
| 2507 PreservePositionScope pos_scope(masm()->positions_recorder()); | 2507 PreservePositionScope pos_scope(masm()->positions_recorder()); |
| 2508 VisitForStackValue(callee); | 2508 VisitForStackValue(callee); |
| 2509 __ LoadRoot(x10, Heap::kUndefinedValueRootIndex); | 2509 __ LoadRoot(x10, Heap::kUndefinedValueRootIndex); |
| 2510 __ Push(x10); // Reserved receiver slot. | 2510 __ Push(x10); // Reserved receiver slot. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2550 // by eval-introduced variables. | 2550 // by eval-introduced variables. |
| 2551 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); | 2551 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); |
| 2552 } | 2552 } |
| 2553 | 2553 |
| 2554 __ Bind(&slow); | 2554 __ Bind(&slow); |
| 2555 // Call the runtime to find the function to call (returned in x0) | 2555 // Call the runtime to find the function to call (returned in x0) |
| 2556 // and the object holding it (returned in x1). | 2556 // and the object holding it (returned in x1). |
| 2557 __ Push(context_register()); | 2557 __ Push(context_register()); |
| 2558 __ Mov(x10, Operand(proxy->name())); | 2558 __ Mov(x10, Operand(proxy->name())); |
| 2559 __ Push(x10); | 2559 __ Push(x10); |
| 2560 __ CallRuntime(Runtime::kLoadContextSlot, 2); | 2560 __ CallRuntime(Runtime::kHiddenLoadContextSlot, 2); |
| 2561 __ Push(x0, x1); // Receiver, function. | 2561 __ Push(x0, x1); // Receiver, function. |
| 2562 | 2562 |
| 2563 // If fast case code has been generated, emit code to push the | 2563 // If fast case code has been generated, emit code to push the |
| 2564 // function and receiver and have the slow path jump around this | 2564 // function and receiver and have the slow path jump around this |
| 2565 // code. | 2565 // code. |
| 2566 if (done.is_linked()) { | 2566 if (done.is_linked()) { |
| 2567 Label call; | 2567 Label call; |
| 2568 __ B(&call); | 2568 __ B(&call); |
| 2569 __ Bind(&done); | 2569 __ Bind(&done); |
| 2570 // Push function. | 2570 // Push function. |
| (...skipping 653 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3224 __ B(&done); | 3224 __ B(&done); |
| 3225 } | 3225 } |
| 3226 | 3226 |
| 3227 __ Bind(&runtime); | 3227 __ Bind(&runtime); |
| 3228 __ Mov(x1, index); | 3228 __ Mov(x1, index); |
| 3229 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); | 3229 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); |
| 3230 __ B(&done); | 3230 __ B(&done); |
| 3231 } | 3231 } |
| 3232 | 3232 |
| 3233 __ Bind(¬_date_object); | 3233 __ Bind(¬_date_object); |
| 3234 __ CallRuntime(Runtime::kThrowNotDateError, 0); | 3234 __ CallRuntime(Runtime::kHiddenThrowNotDateError, 0); |
| 3235 __ Bind(&done); | 3235 __ Bind(&done); |
| 3236 context()->Plug(x0); | 3236 context()->Plug(x0); |
| 3237 } | 3237 } |
| 3238 | 3238 |
| 3239 | 3239 |
| 3240 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { | 3240 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { |
| 3241 ZoneList<Expression*>* args = expr->arguments(); | 3241 ZoneList<Expression*>* args = expr->arguments(); |
| 3242 ASSERT_EQ(3, args->length()); | 3242 ASSERT_EQ(3, args->length()); |
| 3243 | 3243 |
| 3244 Register string = x0; | 3244 Register string = x0; |
| (...skipping 693 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3938 context()->Plug(x0); | 3938 context()->Plug(x0); |
| 3939 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 3939 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
| 3940 // Result of deleting non-global, non-dynamic variables is false. | 3940 // Result of deleting non-global, non-dynamic variables is false. |
| 3941 // The subexpression does not have side effects. | 3941 // The subexpression does not have side effects. |
| 3942 context()->Plug(var->is_this()); | 3942 context()->Plug(var->is_this()); |
| 3943 } else { | 3943 } else { |
| 3944 // Non-global variable. Call the runtime to try to delete from the | 3944 // Non-global variable. Call the runtime to try to delete from the |
| 3945 // context where the variable was introduced. | 3945 // context where the variable was introduced. |
| 3946 __ Mov(x2, Operand(var->name())); | 3946 __ Mov(x2, Operand(var->name())); |
| 3947 __ Push(context_register(), x2); | 3947 __ Push(context_register(), x2); |
| 3948 __ CallRuntime(Runtime::kDeleteContextSlot, 2); | 3948 __ CallRuntime(Runtime::kHiddenDeleteContextSlot, 2); |
| 3949 context()->Plug(x0); | 3949 context()->Plug(x0); |
| 3950 } | 3950 } |
| 3951 } else { | 3951 } else { |
| 3952 // Result of deleting non-property, non-variable reference is true. | 3952 // Result of deleting non-property, non-variable reference is true. |
| 3953 // The subexpression may have side effects. | 3953 // The subexpression may have side effects. |
| 3954 VisitForEffect(expr->expression()); | 3954 VisitForEffect(expr->expression()); |
| 3955 context()->Plug(true); | 3955 context()->Plug(true); |
| 3956 } | 3956 } |
| 3957 break; | 3957 break; |
| 3958 break; | 3958 break; |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4218 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { | 4218 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { |
| 4219 Label done, slow; | 4219 Label done, slow; |
| 4220 | 4220 |
| 4221 // Generate code for loading from variables potentially shadowed | 4221 // Generate code for loading from variables potentially shadowed |
| 4222 // by eval-introduced variables. | 4222 // by eval-introduced variables. |
| 4223 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); | 4223 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); |
| 4224 | 4224 |
| 4225 __ Bind(&slow); | 4225 __ Bind(&slow); |
| 4226 __ Mov(x0, Operand(proxy->name())); | 4226 __ Mov(x0, Operand(proxy->name())); |
| 4227 __ Push(cp, x0); | 4227 __ Push(cp, x0); |
| 4228 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); | 4228 __ CallRuntime(Runtime::kHiddenLoadContextSlotNoReferenceError, 2); |
| 4229 PrepareForBailout(expr, TOS_REG); | 4229 PrepareForBailout(expr, TOS_REG); |
| 4230 __ Bind(&done); | 4230 __ Bind(&done); |
| 4231 | 4231 |
| 4232 context()->Plug(x0); | 4232 context()->Plug(x0); |
| 4233 } else { | 4233 } else { |
| 4234 // This expression cannot throw a reference error at the top level. | 4234 // This expression cannot throw a reference error at the top level. |
| 4235 VisitInDuplicateContext(expr); | 4235 VisitInDuplicateContext(expr); |
| 4236 } | 4236 } |
| 4237 } | 4237 } |
| 4238 | 4238 |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4469 __ Mov(x1, Smi::FromInt(continuation.pos())); | 4469 __ Mov(x1, Smi::FromInt(continuation.pos())); |
| 4470 __ Str(x1, FieldMemOperand(x0, JSGeneratorObject::kContinuationOffset)); | 4470 __ Str(x1, FieldMemOperand(x0, JSGeneratorObject::kContinuationOffset)); |
| 4471 __ Str(cp, FieldMemOperand(x0, JSGeneratorObject::kContextOffset)); | 4471 __ Str(cp, FieldMemOperand(x0, JSGeneratorObject::kContextOffset)); |
| 4472 __ Mov(x1, cp); | 4472 __ Mov(x1, cp); |
| 4473 __ RecordWriteField(x0, JSGeneratorObject::kContextOffset, x1, x2, | 4473 __ RecordWriteField(x0, JSGeneratorObject::kContextOffset, x1, x2, |
| 4474 kLRHasBeenSaved, kDontSaveFPRegs); | 4474 kLRHasBeenSaved, kDontSaveFPRegs); |
| 4475 __ Add(x1, fp, StandardFrameConstants::kExpressionsOffset); | 4475 __ Add(x1, fp, StandardFrameConstants::kExpressionsOffset); |
| 4476 __ Cmp(__ StackPointer(), x1); | 4476 __ Cmp(__ StackPointer(), x1); |
| 4477 __ B(eq, &post_runtime); | 4477 __ B(eq, &post_runtime); |
| 4478 __ Push(x0); // generator object | 4478 __ Push(x0); // generator object |
| 4479 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 4479 __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1); |
| 4480 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4480 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 4481 __ Bind(&post_runtime); | 4481 __ Bind(&post_runtime); |
| 4482 __ Pop(result_register()); | 4482 __ Pop(result_register()); |
| 4483 EmitReturnSequence(); | 4483 EmitReturnSequence(); |
| 4484 | 4484 |
| 4485 __ Bind(&resume); | 4485 __ Bind(&resume); |
| 4486 context()->Plug(result_register()); | 4486 context()->Plug(result_register()); |
| 4487 break; | 4487 break; |
| 4488 } | 4488 } |
| 4489 | 4489 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4540 const int generator_object_depth = kPointerSize + handler_size; | 4540 const int generator_object_depth = kPointerSize + handler_size; |
| 4541 __ Peek(x0, generator_object_depth); | 4541 __ Peek(x0, generator_object_depth); |
| 4542 __ Push(x0); // g | 4542 __ Push(x0); // g |
| 4543 ASSERT((l_continuation.pos() > 0) && Smi::IsValid(l_continuation.pos())); | 4543 ASSERT((l_continuation.pos() > 0) && Smi::IsValid(l_continuation.pos())); |
| 4544 __ Mov(x1, Smi::FromInt(l_continuation.pos())); | 4544 __ Mov(x1, Smi::FromInt(l_continuation.pos())); |
| 4545 __ Str(x1, FieldMemOperand(x0, JSGeneratorObject::kContinuationOffset)); | 4545 __ Str(x1, FieldMemOperand(x0, JSGeneratorObject::kContinuationOffset)); |
| 4546 __ Str(cp, FieldMemOperand(x0, JSGeneratorObject::kContextOffset)); | 4546 __ Str(cp, FieldMemOperand(x0, JSGeneratorObject::kContextOffset)); |
| 4547 __ Mov(x1, cp); | 4547 __ Mov(x1, cp); |
| 4548 __ RecordWriteField(x0, JSGeneratorObject::kContextOffset, x1, x2, | 4548 __ RecordWriteField(x0, JSGeneratorObject::kContextOffset, x1, x2, |
| 4549 kLRHasBeenSaved, kDontSaveFPRegs); | 4549 kLRHasBeenSaved, kDontSaveFPRegs); |
| 4550 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 4550 __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1); |
| 4551 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4551 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 4552 __ Pop(x0); // result | 4552 __ Pop(x0); // result |
| 4553 EmitReturnSequence(); | 4553 EmitReturnSequence(); |
| 4554 __ Bind(&l_resume); // received in x0 | 4554 __ Bind(&l_resume); // received in x0 |
| 4555 __ PopTryHandler(); | 4555 __ PopTryHandler(); |
| 4556 | 4556 |
| 4557 // receiver = iter; f = 'next'; arg = received; | 4557 // receiver = iter; f = 'next'; arg = received; |
| 4558 __ Bind(&l_next); | 4558 __ Bind(&l_next); |
| 4559 __ LoadRoot(x2, Heap::knext_stringRootIndex); // "next" | 4559 __ LoadRoot(x2, Heap::knext_stringRootIndex); // "next" |
| 4560 __ Peek(x3, 1 * kPointerSize); // iter | 4560 __ Peek(x3, 1 * kPointerSize); // iter |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4599 Expression *value, | 4599 Expression *value, |
| 4600 JSGeneratorObject::ResumeMode resume_mode) { | 4600 JSGeneratorObject::ResumeMode resume_mode) { |
| 4601 ASM_LOCATION("FullCodeGenerator::EmitGeneratorResume"); | 4601 ASM_LOCATION("FullCodeGenerator::EmitGeneratorResume"); |
| 4602 Register value_reg = x0; | 4602 Register value_reg = x0; |
| 4603 Register generator_object = x1; | 4603 Register generator_object = x1; |
| 4604 Register the_hole = x2; | 4604 Register the_hole = x2; |
| 4605 Register operand_stack_size = w3; | 4605 Register operand_stack_size = w3; |
| 4606 Register function = x4; | 4606 Register function = x4; |
| 4607 | 4607 |
| 4608 // The value stays in x0, and is ultimately read by the resumed generator, as | 4608 // The value stays in x0, and is ultimately read by the resumed generator, as |
| 4609 // if the CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it | 4609 // if CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject) returned it. Or it |
| 4610 // is read to throw the value when the resumed generator is already closed. r1 | 4610 // is read to throw the value when the resumed generator is already closed. r1 |
| 4611 // will hold the generator object until the activation has been resumed. | 4611 // will hold the generator object until the activation has been resumed. |
| 4612 VisitForStackValue(generator); | 4612 VisitForStackValue(generator); |
| 4613 VisitForAccumulatorValue(value); | 4613 VisitForAccumulatorValue(value); |
| 4614 __ Pop(generator_object); | 4614 __ Pop(generator_object); |
| 4615 | 4615 |
| 4616 // Check generator state. | 4616 // Check generator state. |
| 4617 Label wrong_state, closed_state, done; | 4617 Label wrong_state, closed_state, done; |
| 4618 __ Ldr(x10, FieldMemOperand(generator_object, | 4618 __ Ldr(x10, FieldMemOperand(generator_object, |
| 4619 JSGeneratorObject::kContinuationOffset)); | 4619 JSGeneratorObject::kContinuationOffset)); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4681 | 4681 |
| 4682 __ Bind(&slow_resume); | 4682 __ Bind(&slow_resume); |
| 4683 } | 4683 } |
| 4684 | 4684 |
| 4685 // Otherwise, we push holes for the operand stack and call the runtime to fix | 4685 // Otherwise, we push holes for the operand stack and call the runtime to fix |
| 4686 // up the stack and the handlers. | 4686 // up the stack and the handlers. |
| 4687 __ PushMultipleTimes(the_hole, operand_stack_size); | 4687 __ PushMultipleTimes(the_hole, operand_stack_size); |
| 4688 | 4688 |
| 4689 __ Mov(x10, Smi::FromInt(resume_mode)); | 4689 __ Mov(x10, Smi::FromInt(resume_mode)); |
| 4690 __ Push(generator_object, result_register(), x10); | 4690 __ Push(generator_object, result_register(), x10); |
| 4691 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); | 4691 __ CallRuntime(Runtime::kHiddenResumeJSGeneratorObject, 3); |
| 4692 // Not reached: the runtime call returns elsewhere. | 4692 // Not reached: the runtime call returns elsewhere. |
| 4693 __ Unreachable(); | 4693 __ Unreachable(); |
| 4694 | 4694 |
| 4695 // Reach here when generator is closed. | 4695 // Reach here when generator is closed. |
| 4696 __ Bind(&closed_state); | 4696 __ Bind(&closed_state); |
| 4697 if (resume_mode == JSGeneratorObject::NEXT) { | 4697 if (resume_mode == JSGeneratorObject::NEXT) { |
| 4698 // Return completed iterator result when generator is closed. | 4698 // Return completed iterator result when generator is closed. |
| 4699 __ LoadRoot(x10, Heap::kUndefinedValueRootIndex); | 4699 __ LoadRoot(x10, Heap::kUndefinedValueRootIndex); |
| 4700 __ Push(x10); | 4700 __ Push(x10); |
| 4701 // Pop value from top-of-stack slot; box result into result register. | 4701 // Pop value from top-of-stack slot; box result into result register. |
| 4702 EmitCreateIteratorResult(true); | 4702 EmitCreateIteratorResult(true); |
| 4703 } else { | 4703 } else { |
| 4704 // Throw the provided value. | 4704 // Throw the provided value. |
| 4705 __ Push(value_reg); | 4705 __ Push(value_reg); |
| 4706 __ CallRuntime(Runtime::kThrow, 1); | 4706 __ CallRuntime(Runtime::kHiddenThrow, 1); |
| 4707 } | 4707 } |
| 4708 __ B(&done); | 4708 __ B(&done); |
| 4709 | 4709 |
| 4710 // Throw error if we attempt to operate on a running generator. | 4710 // Throw error if we attempt to operate on a running generator. |
| 4711 __ Bind(&wrong_state); | 4711 __ Bind(&wrong_state); |
| 4712 __ Push(generator_object); | 4712 __ Push(generator_object); |
| 4713 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); | 4713 __ CallRuntime(Runtime::kHiddenThrowGeneratorStateError, 1); |
| 4714 | 4714 |
| 4715 __ Bind(&done); | 4715 __ Bind(&done); |
| 4716 context()->Plug(result_register()); | 4716 context()->Plug(result_register()); |
| 4717 } | 4717 } |
| 4718 | 4718 |
| 4719 | 4719 |
| 4720 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { | 4720 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { |
| 4721 Label gc_required; | 4721 Label gc_required; |
| 4722 Label allocated; | 4722 Label allocated; |
| 4723 | 4723 |
| 4724 Handle<Map> map(isolate()->native_context()->generator_result_map()); | 4724 Handle<Map> map(isolate()->native_context()->generator_result_map()); |
| 4725 | 4725 |
| 4726 // Allocate and populate an object with this form: { value: VAL, done: DONE } | 4726 // Allocate and populate an object with this form: { value: VAL, done: DONE } |
| 4727 | 4727 |
| 4728 Register result = x0; | 4728 Register result = x0; |
| 4729 __ Allocate(map->instance_size(), result, x10, x11, &gc_required, TAG_OBJECT); | 4729 __ Allocate(map->instance_size(), result, x10, x11, &gc_required, TAG_OBJECT); |
| 4730 __ B(&allocated); | 4730 __ B(&allocated); |
| 4731 | 4731 |
| 4732 __ Bind(&gc_required); | 4732 __ Bind(&gc_required); |
| 4733 __ Push(Smi::FromInt(map->instance_size())); | 4733 __ Push(Smi::FromInt(map->instance_size())); |
| 4734 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); | 4734 __ CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1); |
| 4735 __ Ldr(context_register(), | 4735 __ Ldr(context_register(), |
| 4736 MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4736 MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 4737 | 4737 |
| 4738 __ Bind(&allocated); | 4738 __ Bind(&allocated); |
| 4739 Register map_reg = x1; | 4739 Register map_reg = x1; |
| 4740 Register result_value = x2; | 4740 Register result_value = x2; |
| 4741 Register boolean_done = x3; | 4741 Register boolean_done = x3; |
| 4742 Register empty_fixed_array = x4; | 4742 Register empty_fixed_array = x4; |
| 4743 __ Mov(map_reg, Operand(map)); | 4743 __ Mov(map_reg, Operand(map)); |
| 4744 __ Pop(result_value); | 4744 __ Pop(result_value); |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5006 return previous_; | 5006 return previous_; |
| 5007 } | 5007 } |
| 5008 | 5008 |
| 5009 | 5009 |
| 5010 #undef __ | 5010 #undef __ |
| 5011 | 5011 |
| 5012 | 5012 |
| 5013 } } // namespace v8::internal | 5013 } } // namespace v8::internal |
| 5014 | 5014 |
| 5015 #endif // V8_TARGET_ARCH_ARM64 | 5015 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |