| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_ARM | 7 #if V8_TARGET_ARCH_ARM |
| 8 | 8 |
| 9 #include "src/code-factory.h" | 9 #include "src/code-factory.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 1398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1409 // Check that extension is NULL. | 1409 // Check that extension is NULL. |
| 1410 __ ldr(temp, ContextOperand(next, Context::EXTENSION_INDEX)); | 1410 __ ldr(temp, ContextOperand(next, Context::EXTENSION_INDEX)); |
| 1411 __ tst(temp, temp); | 1411 __ tst(temp, temp); |
| 1412 __ b(ne, slow); | 1412 __ b(ne, slow); |
| 1413 // Load next context in chain. | 1413 // Load next context in chain. |
| 1414 __ ldr(next, ContextOperand(next, Context::PREVIOUS_INDEX)); | 1414 __ ldr(next, ContextOperand(next, Context::PREVIOUS_INDEX)); |
| 1415 __ b(&loop); | 1415 __ b(&loop); |
| 1416 __ bind(&fast); | 1416 __ bind(&fast); |
| 1417 } | 1417 } |
| 1418 | 1418 |
| 1419 __ ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); | 1419 // All extension objects were empty and it is safe to use a normal global |
| 1420 __ mov(LoadDescriptor::NameRegister(), Operand(proxy->var()->name())); | 1420 // load machinery. |
| 1421 __ mov(LoadDescriptor::SlotRegister(), | 1421 EmitGlobalVariableLoad(proxy, typeof_state); |
| 1422 Operand(SmiFromSlot(proxy->VariableFeedbackSlot()))); | |
| 1423 | |
| 1424 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) | |
| 1425 ? NOT_CONTEXTUAL | |
| 1426 : CONTEXTUAL; | |
| 1427 CallLoadIC(mode); | |
| 1428 } | 1422 } |
| 1429 | 1423 |
| 1430 | 1424 |
| 1431 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1425 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
| 1432 Label* slow) { | 1426 Label* slow) { |
| 1433 DCHECK(var->IsContextSlot()); | 1427 DCHECK(var->IsContextSlot()); |
| 1434 Register context = cp; | 1428 Register context = cp; |
| 1435 Register next = r3; | 1429 Register next = r3; |
| 1436 Register temp = r4; | 1430 Register temp = r4; |
| 1437 | 1431 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1486 __ mov(r0, Operand(var->name())); | 1480 __ mov(r0, Operand(var->name())); |
| 1487 __ push(r0); | 1481 __ push(r0); |
| 1488 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1482 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 1489 } | 1483 } |
| 1490 } | 1484 } |
| 1491 __ jmp(done); | 1485 __ jmp(done); |
| 1492 } | 1486 } |
| 1493 } | 1487 } |
| 1494 | 1488 |
| 1495 | 1489 |
| 1496 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { | 1490 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, |
| 1491 TypeofState typeof_state) { |
| 1492 Variable* var = proxy->var(); |
| 1493 DCHECK(var->IsUnallocatedOrGlobalSlot() || |
| 1494 (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL)); |
| 1495 __ ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); |
| 1496 __ mov(LoadDescriptor::NameRegister(), Operand(var->name())); |
| 1497 __ mov(LoadDescriptor::SlotRegister(), |
| 1498 Operand(SmiFromSlot(proxy->VariableFeedbackSlot()))); |
| 1499 // Inside typeof use a regular load, not a contextual load, to avoid |
| 1500 // a reference error. |
| 1501 CallLoadIC(typeof_state == NOT_INSIDE_TYPEOF ? CONTEXTUAL : NOT_CONTEXTUAL); |
| 1502 } |
| 1503 |
| 1504 |
| 1505 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, |
| 1506 TypeofState typeof_state) { |
| 1497 // Record position before possible IC call. | 1507 // Record position before possible IC call. |
| 1498 SetExpressionPosition(proxy); | 1508 SetExpressionPosition(proxy); |
| 1499 PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS); | 1509 PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS); |
| 1500 Variable* var = proxy->var(); | 1510 Variable* var = proxy->var(); |
| 1501 | 1511 |
| 1502 // Three cases: global variables, lookup variables, and all other types of | 1512 // Three cases: global variables, lookup variables, and all other types of |
| 1503 // variables. | 1513 // variables. |
| 1504 switch (var->location()) { | 1514 switch (var->location()) { |
| 1505 case VariableLocation::GLOBAL: | 1515 case VariableLocation::GLOBAL: |
| 1506 case VariableLocation::UNALLOCATED: { | 1516 case VariableLocation::UNALLOCATED: { |
| 1507 Comment cmnt(masm_, "[ Global variable"); | 1517 Comment cmnt(masm_, "[ Global variable"); |
| 1508 __ ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); | 1518 EmitGlobalVariableLoad(proxy, typeof_state); |
| 1509 __ mov(LoadDescriptor::NameRegister(), Operand(var->name())); | |
| 1510 __ mov(LoadDescriptor::SlotRegister(), | |
| 1511 Operand(SmiFromSlot(proxy->VariableFeedbackSlot()))); | |
| 1512 CallGlobalLoadIC(var->name()); | |
| 1513 context()->Plug(r0); | 1519 context()->Plug(r0); |
| 1514 break; | 1520 break; |
| 1515 } | 1521 } |
| 1516 | 1522 |
| 1517 case VariableLocation::PARAMETER: | 1523 case VariableLocation::PARAMETER: |
| 1518 case VariableLocation::LOCAL: | 1524 case VariableLocation::LOCAL: |
| 1519 case VariableLocation::CONTEXT: { | 1525 case VariableLocation::CONTEXT: { |
| 1526 DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_state); |
| 1520 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" | 1527 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" |
| 1521 : "[ Stack variable"); | 1528 : "[ Stack variable"); |
| 1522 if (var->binding_needs_init()) { | 1529 if (var->binding_needs_init()) { |
| 1523 // var->scope() may be NULL when the proxy is located in eval code and | 1530 // var->scope() may be NULL when the proxy is located in eval code and |
| 1524 // refers to a potential outside binding. Currently those bindings are | 1531 // refers to a potential outside binding. Currently those bindings are |
| 1525 // always looked up dynamically, i.e. in that case | 1532 // always looked up dynamically, i.e. in that case |
| 1526 // var->location() == LOOKUP. | 1533 // var->location() == LOOKUP. |
| 1527 // always holds. | 1534 // always holds. |
| 1528 DCHECK(var->scope() != NULL); | 1535 DCHECK(var->scope() != NULL); |
| 1529 | 1536 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1583 } | 1590 } |
| 1584 context()->Plug(var); | 1591 context()->Plug(var); |
| 1585 break; | 1592 break; |
| 1586 } | 1593 } |
| 1587 | 1594 |
| 1588 case VariableLocation::LOOKUP: { | 1595 case VariableLocation::LOOKUP: { |
| 1589 Comment cmnt(masm_, "[ Lookup variable"); | 1596 Comment cmnt(masm_, "[ Lookup variable"); |
| 1590 Label done, slow; | 1597 Label done, slow; |
| 1591 // Generate code for loading from variables potentially shadowed | 1598 // Generate code for loading from variables potentially shadowed |
| 1592 // by eval-introduced variables. | 1599 // by eval-introduced variables. |
| 1593 EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done); | 1600 EmitDynamicLookupFastCase(proxy, typeof_state, &slow, &done); |
| 1594 __ bind(&slow); | 1601 __ bind(&slow); |
| 1595 __ mov(r1, Operand(var->name())); | 1602 __ mov(r1, Operand(var->name())); |
| 1596 __ Push(cp, r1); // Context and name. | 1603 __ Push(cp, r1); // Context and name. |
| 1597 __ CallRuntime(Runtime::kLoadLookupSlot, 2); | 1604 Runtime::FunctionId function_id = |
| 1605 typeof_state == NOT_INSIDE_TYPEOF |
| 1606 ? Runtime::kLoadLookupSlot |
| 1607 : Runtime::kLoadLookupSlotNoReferenceError; |
| 1608 __ CallRuntime(function_id, 2); |
| 1598 __ bind(&done); | 1609 __ bind(&done); |
| 1599 context()->Plug(r0); | 1610 context()->Plug(r0); |
| 1600 } | 1611 } |
| 1601 } | 1612 } |
| 1602 } | 1613 } |
| 1603 | 1614 |
| 1604 | 1615 |
| 1605 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1616 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 1606 Comment cmnt(masm_, "[ RegExpLiteral"); | 1617 Comment cmnt(masm_, "[ RegExpLiteral"); |
| 1607 Label materialized; | 1618 Label materialized; |
| (...skipping 3539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5147 } | 5158 } |
| 5148 } else { | 5159 } else { |
| 5149 context()->Plug(r0); | 5160 context()->Plug(r0); |
| 5150 } | 5161 } |
| 5151 break; | 5162 break; |
| 5152 } | 5163 } |
| 5153 } | 5164 } |
| 5154 } | 5165 } |
| 5155 | 5166 |
| 5156 | 5167 |
| 5157 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | |
| 5158 DCHECK(!context()->IsEffect()); | |
| 5159 DCHECK(!context()->IsTest()); | |
| 5160 VariableProxy* proxy = expr->AsVariableProxy(); | |
| 5161 if (proxy != NULL && proxy->var()->IsUnallocatedOrGlobalSlot()) { | |
| 5162 Comment cmnt(masm_, "[ Global variable"); | |
| 5163 __ ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); | |
| 5164 __ mov(LoadDescriptor::NameRegister(), Operand(proxy->name())); | |
| 5165 __ mov(LoadDescriptor::SlotRegister(), | |
| 5166 Operand(SmiFromSlot(proxy->VariableFeedbackSlot()))); | |
| 5167 // Use a regular load, not a contextual load, to avoid a reference | |
| 5168 // error. | |
| 5169 CallLoadIC(NOT_CONTEXTUAL); | |
| 5170 PrepareForBailout(expr, TOS_REG); | |
| 5171 context()->Plug(r0); | |
| 5172 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { | |
| 5173 Comment cmnt(masm_, "[ Lookup slot"); | |
| 5174 Label done, slow; | |
| 5175 | |
| 5176 // Generate code for loading from variables potentially shadowed | |
| 5177 // by eval-introduced variables. | |
| 5178 EmitDynamicLookupFastCase(proxy, INSIDE_TYPEOF, &slow, &done); | |
| 5179 | |
| 5180 __ bind(&slow); | |
| 5181 __ mov(r0, Operand(proxy->name())); | |
| 5182 __ Push(cp, r0); | |
| 5183 __ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2); | |
| 5184 PrepareForBailout(expr, TOS_REG); | |
| 5185 __ bind(&done); | |
| 5186 | |
| 5187 context()->Plug(r0); | |
| 5188 } else { | |
| 5189 // This expression cannot throw a reference error at the top level. | |
| 5190 VisitInDuplicateContext(expr); | |
| 5191 } | |
| 5192 } | |
| 5193 | |
| 5194 | |
| 5195 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, | 5168 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, |
| 5196 Expression* sub_expr, | 5169 Expression* sub_expr, |
| 5197 Handle<String> check) { | 5170 Handle<String> check) { |
| 5198 Label materialize_true, materialize_false; | 5171 Label materialize_true, materialize_false; |
| 5199 Label* if_true = NULL; | 5172 Label* if_true = NULL; |
| 5200 Label* if_false = NULL; | 5173 Label* if_false = NULL; |
| 5201 Label* fall_through = NULL; | 5174 Label* fall_through = NULL; |
| 5202 context()->PrepareTest(&materialize_true, &materialize_false, | 5175 context()->PrepareTest(&materialize_true, &materialize_false, |
| 5203 &if_true, &if_false, &fall_through); | 5176 &if_true, &if_false, &fall_through); |
| 5204 | 5177 |
| (...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5618 DCHECK(interrupt_address == | 5591 DCHECK(interrupt_address == |
| 5619 isolate->builtins()->OsrAfterStackCheck()->entry()); | 5592 isolate->builtins()->OsrAfterStackCheck()->entry()); |
| 5620 return OSR_AFTER_STACK_CHECK; | 5593 return OSR_AFTER_STACK_CHECK; |
| 5621 } | 5594 } |
| 5622 | 5595 |
| 5623 | 5596 |
| 5624 } // namespace internal | 5597 } // namespace internal |
| 5625 } // namespace v8 | 5598 } // namespace v8 |
| 5626 | 5599 |
| 5627 #endif // V8_TARGET_ARCH_ARM | 5600 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |