| 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-factory.h" | 9 #include "src/code-factory.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 1381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1392 __ JumpIfRoot(temp, Heap::kNativeContextMapRootIndex, &fast); | 1392 __ JumpIfRoot(temp, Heap::kNativeContextMapRootIndex, &fast); |
| 1393 // Check that extension is NULL. | 1393 // Check that extension is NULL. |
| 1394 __ Ldr(temp, ContextMemOperand(next, Context::EXTENSION_INDEX)); | 1394 __ Ldr(temp, ContextMemOperand(next, Context::EXTENSION_INDEX)); |
| 1395 __ Cbnz(temp, slow); | 1395 __ Cbnz(temp, slow); |
| 1396 // Load next context in chain. | 1396 // Load next context in chain. |
| 1397 __ Ldr(next, ContextMemOperand(next, Context::PREVIOUS_INDEX)); | 1397 __ Ldr(next, ContextMemOperand(next, Context::PREVIOUS_INDEX)); |
| 1398 __ B(&loop); | 1398 __ B(&loop); |
| 1399 __ Bind(&fast); | 1399 __ Bind(&fast); |
| 1400 } | 1400 } |
| 1401 | 1401 |
| 1402 __ Ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectMemOperand()); | 1402 // All extension objects were empty and it is safe to use a normal global |
| 1403 __ Mov(LoadDescriptor::NameRegister(), Operand(proxy->var()->name())); | 1403 // load machinery. |
| 1404 __ Mov(LoadDescriptor::SlotRegister(), | 1404 EmitGlobalVariableLoad(proxy, typeof_state); |
| 1405 SmiFromSlot(proxy->VariableFeedbackSlot())); | |
| 1406 | |
| 1407 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) ? NOT_CONTEXTUAL | |
| 1408 : CONTEXTUAL; | |
| 1409 CallLoadIC(mode); | |
| 1410 } | 1405 } |
| 1411 | 1406 |
| 1412 | 1407 |
| 1413 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1408 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
| 1414 Label* slow) { | 1409 Label* slow) { |
| 1415 DCHECK(var->IsContextSlot()); | 1410 DCHECK(var->IsContextSlot()); |
| 1416 Register context = cp; | 1411 Register context = cp; |
| 1417 Register next = x10; | 1412 Register next = x10; |
| 1418 Register temp = x11; | 1413 Register temp = x11; |
| 1419 | 1414 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1465 __ Mov(x0, Operand(var->name())); | 1460 __ Mov(x0, Operand(var->name())); |
| 1466 __ Push(x0); | 1461 __ Push(x0); |
| 1467 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1462 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 1468 } | 1463 } |
| 1469 } | 1464 } |
| 1470 __ B(done); | 1465 __ B(done); |
| 1471 } | 1466 } |
| 1472 } | 1467 } |
| 1473 | 1468 |
| 1474 | 1469 |
| 1475 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { | 1470 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, |
| 1471 TypeofState typeof_state) { |
| 1472 Variable* var = proxy->var(); |
| 1473 DCHECK(var->IsUnallocatedOrGlobalSlot() || |
| 1474 (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL)); |
| 1475 __ Ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectMemOperand()); |
| 1476 __ Mov(LoadDescriptor::NameRegister(), Operand(var->name())); |
| 1477 __ Mov(LoadDescriptor::SlotRegister(), |
| 1478 SmiFromSlot(proxy->VariableFeedbackSlot())); |
| 1479 // Inside typeof use a regular load, not a contextual load, to avoid |
| 1480 // a reference error. |
| 1481 CallLoadIC(typeof_state == NOT_INSIDE_TYPEOF ? CONTEXTUAL : NOT_CONTEXTUAL); |
| 1482 } |
| 1483 |
| 1484 |
| 1485 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, |
| 1486 TypeofState typeof_state) { |
| 1476 // Record position before possible IC call. | 1487 // Record position before possible IC call. |
| 1477 SetExpressionPosition(proxy); | 1488 SetExpressionPosition(proxy); |
| 1478 PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS); | 1489 PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS); |
| 1479 Variable* var = proxy->var(); | 1490 Variable* var = proxy->var(); |
| 1480 | 1491 |
| 1481 // Three cases: global variables, lookup variables, and all other types of | 1492 // Three cases: global variables, lookup variables, and all other types of |
| 1482 // variables. | 1493 // variables. |
| 1483 switch (var->location()) { | 1494 switch (var->location()) { |
| 1484 case VariableLocation::GLOBAL: | 1495 case VariableLocation::GLOBAL: |
| 1485 case VariableLocation::UNALLOCATED: { | 1496 case VariableLocation::UNALLOCATED: { |
| 1486 Comment cmnt(masm_, "Global variable"); | 1497 Comment cmnt(masm_, "Global variable"); |
| 1487 __ Ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectMemOperand()); | 1498 EmitGlobalVariableLoad(proxy, typeof_state); |
| 1488 __ Mov(LoadDescriptor::NameRegister(), Operand(var->name())); | |
| 1489 __ Mov(LoadDescriptor::SlotRegister(), | |
| 1490 SmiFromSlot(proxy->VariableFeedbackSlot())); | |
| 1491 CallGlobalLoadIC(var->name()); | |
| 1492 context()->Plug(x0); | 1499 context()->Plug(x0); |
| 1493 break; | 1500 break; |
| 1494 } | 1501 } |
| 1495 | 1502 |
| 1496 case VariableLocation::PARAMETER: | 1503 case VariableLocation::PARAMETER: |
| 1497 case VariableLocation::LOCAL: | 1504 case VariableLocation::LOCAL: |
| 1498 case VariableLocation::CONTEXT: { | 1505 case VariableLocation::CONTEXT: { |
| 1506 DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_state); |
| 1499 Comment cmnt(masm_, var->IsContextSlot() | 1507 Comment cmnt(masm_, var->IsContextSlot() |
| 1500 ? "Context variable" | 1508 ? "Context variable" |
| 1501 : "Stack variable"); | 1509 : "Stack variable"); |
| 1502 if (var->binding_needs_init()) { | 1510 if (var->binding_needs_init()) { |
| 1503 // var->scope() may be NULL when the proxy is located in eval code and | 1511 // var->scope() may be NULL when the proxy is located in eval code and |
| 1504 // refers to a potential outside binding. Currently those bindings are | 1512 // refers to a potential outside binding. Currently those bindings are |
| 1505 // always looked up dynamically, i.e. in that case | 1513 // always looked up dynamically, i.e. in that case |
| 1506 // var->location() == LOOKUP. | 1514 // var->location() == LOOKUP. |
| 1507 // always holds. | 1515 // always holds. |
| 1508 DCHECK(var->scope() != NULL); | 1516 DCHECK(var->scope() != NULL); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1562 } | 1570 } |
| 1563 } | 1571 } |
| 1564 context()->Plug(var); | 1572 context()->Plug(var); |
| 1565 break; | 1573 break; |
| 1566 } | 1574 } |
| 1567 | 1575 |
| 1568 case VariableLocation::LOOKUP: { | 1576 case VariableLocation::LOOKUP: { |
| 1569 Label done, slow; | 1577 Label done, slow; |
| 1570 // Generate code for loading from variables potentially shadowed by | 1578 // Generate code for loading from variables potentially shadowed by |
| 1571 // eval-introduced variables. | 1579 // eval-introduced variables. |
| 1572 EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done); | 1580 EmitDynamicLookupFastCase(proxy, typeof_state, &slow, &done); |
| 1573 __ Bind(&slow); | 1581 __ Bind(&slow); |
| 1574 Comment cmnt(masm_, "Lookup variable"); | 1582 Comment cmnt(masm_, "Lookup variable"); |
| 1575 __ Mov(x1, Operand(var->name())); | 1583 __ Mov(x1, Operand(var->name())); |
| 1576 __ Push(cp, x1); // Context and name. | 1584 __ Push(cp, x1); // Context and name. |
| 1577 __ CallRuntime(Runtime::kLoadLookupSlot, 2); | 1585 Runtime::FunctionId function_id = |
| 1586 typeof_state == NOT_INSIDE_TYPEOF |
| 1587 ? Runtime::kLoadLookupSlot |
| 1588 : Runtime::kLoadLookupSlotNoReferenceError; |
| 1589 __ CallRuntime(function_id, 2); |
| 1578 __ Bind(&done); | 1590 __ Bind(&done); |
| 1579 context()->Plug(x0); | 1591 context()->Plug(x0); |
| 1580 break; | 1592 break; |
| 1581 } | 1593 } |
| 1582 } | 1594 } |
| 1583 } | 1595 } |
| 1584 | 1596 |
| 1585 | 1597 |
| 1586 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1598 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 1587 Comment cmnt(masm_, "[ RegExpLiteral"); | 1599 Comment cmnt(masm_, "[ RegExpLiteral"); |
| (...skipping 3246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4834 } | 4846 } |
| 4835 } else { | 4847 } else { |
| 4836 context()->Plug(x0); | 4848 context()->Plug(x0); |
| 4837 } | 4849 } |
| 4838 break; | 4850 break; |
| 4839 } | 4851 } |
| 4840 } | 4852 } |
| 4841 } | 4853 } |
| 4842 | 4854 |
| 4843 | 4855 |
| 4844 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | |
| 4845 DCHECK(!context()->IsEffect()); | |
| 4846 DCHECK(!context()->IsTest()); | |
| 4847 VariableProxy* proxy = expr->AsVariableProxy(); | |
| 4848 if (proxy != NULL && proxy->var()->IsUnallocatedOrGlobalSlot()) { | |
| 4849 Comment cmnt(masm_, "Global variable"); | |
| 4850 __ Ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectMemOperand()); | |
| 4851 __ Mov(LoadDescriptor::NameRegister(), Operand(proxy->name())); | |
| 4852 __ Mov(LoadDescriptor::SlotRegister(), | |
| 4853 SmiFromSlot(proxy->VariableFeedbackSlot())); | |
| 4854 // Use a regular load, not a contextual load, to avoid a reference | |
| 4855 // error. | |
| 4856 CallLoadIC(NOT_CONTEXTUAL); | |
| 4857 PrepareForBailout(expr, TOS_REG); | |
| 4858 context()->Plug(x0); | |
| 4859 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { | |
| 4860 Label done, slow; | |
| 4861 | |
| 4862 // Generate code for loading from variables potentially shadowed | |
| 4863 // by eval-introduced variables. | |
| 4864 EmitDynamicLookupFastCase(proxy, INSIDE_TYPEOF, &slow, &done); | |
| 4865 | |
| 4866 __ Bind(&slow); | |
| 4867 __ Mov(x0, Operand(proxy->name())); | |
| 4868 __ Push(cp, x0); | |
| 4869 __ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2); | |
| 4870 PrepareForBailout(expr, TOS_REG); | |
| 4871 __ Bind(&done); | |
| 4872 | |
| 4873 context()->Plug(x0); | |
| 4874 } else { | |
| 4875 // This expression cannot throw a reference error at the top level. | |
| 4876 VisitInDuplicateContext(expr); | |
| 4877 } | |
| 4878 } | |
| 4879 | |
| 4880 | |
| 4881 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, | 4856 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, |
| 4882 Expression* sub_expr, | 4857 Expression* sub_expr, |
| 4883 Handle<String> check) { | 4858 Handle<String> check) { |
| 4884 ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof"); | 4859 ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof"); |
| 4885 Comment cmnt(masm_, "[ EmitLiteralCompareTypeof"); | 4860 Comment cmnt(masm_, "[ EmitLiteralCompareTypeof"); |
| 4886 Label materialize_true, materialize_false; | 4861 Label materialize_true, materialize_false; |
| 4887 Label* if_true = NULL; | 4862 Label* if_true = NULL; |
| 4888 Label* if_false = NULL; | 4863 Label* if_false = NULL; |
| 4889 Label* fall_through = NULL; | 4864 Label* fall_through = NULL; |
| 4890 context()->PrepareTest(&materialize_true, &materialize_false, | 4865 context()->PrepareTest(&materialize_true, &materialize_false, |
| (...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5594 } | 5569 } |
| 5595 | 5570 |
| 5596 return INTERRUPT; | 5571 return INTERRUPT; |
| 5597 } | 5572 } |
| 5598 | 5573 |
| 5599 | 5574 |
| 5600 } // namespace internal | 5575 } // namespace internal |
| 5601 } // namespace v8 | 5576 } // namespace v8 |
| 5602 | 5577 |
| 5603 #endif // V8_TARGET_ARCH_ARM64 | 5578 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |