| 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_X64 | 7 #if V8_TARGET_ARCH_X64 |
| 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 1363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1374 __ j(equal, &fast, Label::kNear); | 1374 __ j(equal, &fast, Label::kNear); |
| 1375 // Check that extension is NULL. | 1375 // Check that extension is NULL. |
| 1376 __ cmpp(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0)); | 1376 __ cmpp(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0)); |
| 1377 __ j(not_equal, slow); | 1377 __ j(not_equal, slow); |
| 1378 // Load next context in chain. | 1378 // Load next context in chain. |
| 1379 __ movp(temp, ContextOperand(temp, Context::PREVIOUS_INDEX)); | 1379 __ movp(temp, ContextOperand(temp, Context::PREVIOUS_INDEX)); |
| 1380 __ jmp(&next); | 1380 __ jmp(&next); |
| 1381 __ bind(&fast); | 1381 __ bind(&fast); |
| 1382 } | 1382 } |
| 1383 | 1383 |
| 1384 // All extension objects were empty and it is safe to use a global | 1384 // All extension objects were empty and it is safe to use a normal global |
| 1385 // load IC call. | 1385 // load machinery. |
| 1386 __ movp(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); | 1386 EmitGlobalVariableLoad(proxy, typeof_state); |
| 1387 __ Move(LoadDescriptor::NameRegister(), proxy->var()->name()); | |
| 1388 __ Move(LoadDescriptor::SlotRegister(), | |
| 1389 SmiFromSlot(proxy->VariableFeedbackSlot())); | |
| 1390 | |
| 1391 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) | |
| 1392 ? NOT_CONTEXTUAL | |
| 1393 : CONTEXTUAL; | |
| 1394 CallLoadIC(mode); | |
| 1395 } | 1387 } |
| 1396 | 1388 |
| 1397 | 1389 |
| 1398 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1390 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
| 1399 Label* slow) { | 1391 Label* slow) { |
| 1400 DCHECK(var->IsContextSlot()); | 1392 DCHECK(var->IsContextSlot()); |
| 1401 Register context = rsi; | 1393 Register context = rsi; |
| 1402 Register temp = rbx; | 1394 Register temp = rbx; |
| 1403 | 1395 |
| 1404 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { | 1396 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1450 } else { // LET || CONST | 1442 } else { // LET || CONST |
| 1451 __ Push(var->name()); | 1443 __ Push(var->name()); |
| 1452 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1444 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 1453 } | 1445 } |
| 1454 } | 1446 } |
| 1455 __ jmp(done); | 1447 __ jmp(done); |
| 1456 } | 1448 } |
| 1457 } | 1449 } |
| 1458 | 1450 |
| 1459 | 1451 |
| 1460 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { | 1452 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, |
| 1453 TypeofState typeof_state) { |
| 1454 Variable* var = proxy->var(); |
| 1455 DCHECK(var->IsUnallocatedOrGlobalSlot() || |
| 1456 (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL)); |
| 1457 __ Move(LoadDescriptor::NameRegister(), var->name()); |
| 1458 __ movp(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); |
| 1459 __ Move(LoadDescriptor::SlotRegister(), |
| 1460 SmiFromSlot(proxy->VariableFeedbackSlot())); |
| 1461 // Inside typeof use a regular load, not a contextual load, to avoid |
| 1462 // a reference error. |
| 1463 CallLoadIC(typeof_state == NOT_INSIDE_TYPEOF ? CONTEXTUAL : NOT_CONTEXTUAL); |
| 1464 } |
| 1465 |
| 1466 |
| 1467 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, |
| 1468 TypeofState typeof_state) { |
| 1461 // Record position before possible IC call. | 1469 // Record position before possible IC call. |
| 1462 SetExpressionPosition(proxy); | 1470 SetExpressionPosition(proxy); |
| 1463 PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS); | 1471 PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS); |
| 1464 Variable* var = proxy->var(); | 1472 Variable* var = proxy->var(); |
| 1465 | 1473 |
| 1466 // Three cases: global variables, lookup variables, and all other types of | 1474 // Three cases: global variables, lookup variables, and all other types of |
| 1467 // variables. | 1475 // variables. |
| 1468 switch (var->location()) { | 1476 switch (var->location()) { |
| 1469 case VariableLocation::GLOBAL: | 1477 case VariableLocation::GLOBAL: |
| 1470 case VariableLocation::UNALLOCATED: { | 1478 case VariableLocation::UNALLOCATED: { |
| 1471 Comment cmnt(masm_, "[ Global variable"); | 1479 Comment cmnt(masm_, "[ Global variable"); |
| 1472 __ Move(LoadDescriptor::NameRegister(), var->name()); | 1480 EmitGlobalVariableLoad(proxy, typeof_state); |
| 1473 __ movp(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); | |
| 1474 __ Move(LoadDescriptor::SlotRegister(), | |
| 1475 SmiFromSlot(proxy->VariableFeedbackSlot())); | |
| 1476 CallGlobalLoadIC(var->name()); | |
| 1477 context()->Plug(rax); | 1481 context()->Plug(rax); |
| 1478 break; | 1482 break; |
| 1479 } | 1483 } |
| 1480 | 1484 |
| 1481 case VariableLocation::PARAMETER: | 1485 case VariableLocation::PARAMETER: |
| 1482 case VariableLocation::LOCAL: | 1486 case VariableLocation::LOCAL: |
| 1483 case VariableLocation::CONTEXT: { | 1487 case VariableLocation::CONTEXT: { |
| 1488 DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_state); |
| 1484 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context slot" | 1489 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context slot" |
| 1485 : "[ Stack slot"); | 1490 : "[ Stack slot"); |
| 1486 if (var->binding_needs_init()) { | 1491 if (var->binding_needs_init()) { |
| 1487 // var->scope() may be NULL when the proxy is located in eval code and | 1492 // var->scope() may be NULL when the proxy is located in eval code and |
| 1488 // refers to a potential outside binding. Currently those bindings are | 1493 // refers to a potential outside binding. Currently those bindings are |
| 1489 // always looked up dynamically, i.e. in that case | 1494 // always looked up dynamically, i.e. in that case |
| 1490 // var->location() == LOOKUP. | 1495 // var->location() == LOOKUP. |
| 1491 // always holds. | 1496 // always holds. |
| 1492 DCHECK(var->scope() != NULL); | 1497 DCHECK(var->scope() != NULL); |
| 1493 | 1498 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1546 } | 1551 } |
| 1547 context()->Plug(var); | 1552 context()->Plug(var); |
| 1548 break; | 1553 break; |
| 1549 } | 1554 } |
| 1550 | 1555 |
| 1551 case VariableLocation::LOOKUP: { | 1556 case VariableLocation::LOOKUP: { |
| 1552 Comment cmnt(masm_, "[ Lookup slot"); | 1557 Comment cmnt(masm_, "[ Lookup slot"); |
| 1553 Label done, slow; | 1558 Label done, slow; |
| 1554 // Generate code for loading from variables potentially shadowed | 1559 // Generate code for loading from variables potentially shadowed |
| 1555 // by eval-introduced variables. | 1560 // by eval-introduced variables. |
| 1556 EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done); | 1561 EmitDynamicLookupFastCase(proxy, typeof_state, &slow, &done); |
| 1557 __ bind(&slow); | 1562 __ bind(&slow); |
| 1558 __ Push(rsi); // Context. | 1563 __ Push(rsi); // Context. |
| 1559 __ Push(var->name()); | 1564 __ Push(var->name()); |
| 1560 __ CallRuntime(Runtime::kLoadLookupSlot, 2); | 1565 Runtime::FunctionId function_id = |
| 1566 typeof_state == NOT_INSIDE_TYPEOF |
| 1567 ? Runtime::kLoadLookupSlot |
| 1568 : Runtime::kLoadLookupSlotNoReferenceError; |
| 1569 __ CallRuntime(function_id, 2); |
| 1561 __ bind(&done); | 1570 __ bind(&done); |
| 1562 context()->Plug(rax); | 1571 context()->Plug(rax); |
| 1563 break; | 1572 break; |
| 1564 } | 1573 } |
| 1565 } | 1574 } |
| 1566 } | 1575 } |
| 1567 | 1576 |
| 1568 | 1577 |
| 1569 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1578 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 1570 Comment cmnt(masm_, "[ RegExpLiteral"); | 1579 Comment cmnt(masm_, "[ RegExpLiteral"); |
| (...skipping 3534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5105 } | 5114 } |
| 5106 } else { | 5115 } else { |
| 5107 context()->Plug(rax); | 5116 context()->Plug(rax); |
| 5108 } | 5117 } |
| 5109 break; | 5118 break; |
| 5110 } | 5119 } |
| 5111 } | 5120 } |
| 5112 } | 5121 } |
| 5113 | 5122 |
| 5114 | 5123 |
| 5115 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | |
| 5116 VariableProxy* proxy = expr->AsVariableProxy(); | |
| 5117 DCHECK(!context()->IsEffect()); | |
| 5118 DCHECK(!context()->IsTest()); | |
| 5119 | |
| 5120 if (proxy != NULL && proxy->var()->IsUnallocatedOrGlobalSlot()) { | |
| 5121 Comment cmnt(masm_, "[ Global variable"); | |
| 5122 __ Move(LoadDescriptor::NameRegister(), proxy->name()); | |
| 5123 __ movp(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); | |
| 5124 __ Move(LoadDescriptor::SlotRegister(), | |
| 5125 SmiFromSlot(proxy->VariableFeedbackSlot())); | |
| 5126 // Use a regular load, not a contextual load, to avoid a reference | |
| 5127 // error. | |
| 5128 CallLoadIC(NOT_CONTEXTUAL); | |
| 5129 PrepareForBailout(expr, TOS_REG); | |
| 5130 context()->Plug(rax); | |
| 5131 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { | |
| 5132 Comment cmnt(masm_, "[ Lookup slot"); | |
| 5133 Label done, slow; | |
| 5134 | |
| 5135 // Generate code for loading from variables potentially shadowed | |
| 5136 // by eval-introduced variables. | |
| 5137 EmitDynamicLookupFastCase(proxy, INSIDE_TYPEOF, &slow, &done); | |
| 5138 | |
| 5139 __ bind(&slow); | |
| 5140 __ Push(rsi); | |
| 5141 __ Push(proxy->name()); | |
| 5142 __ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2); | |
| 5143 PrepareForBailout(expr, TOS_REG); | |
| 5144 __ bind(&done); | |
| 5145 | |
| 5146 context()->Plug(rax); | |
| 5147 } else { | |
| 5148 // This expression cannot throw a reference error at the top level. | |
| 5149 VisitInDuplicateContext(expr); | |
| 5150 } | |
| 5151 } | |
| 5152 | |
| 5153 | |
| 5154 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, | 5124 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, |
| 5155 Expression* sub_expr, | 5125 Expression* sub_expr, |
| 5156 Handle<String> check) { | 5126 Handle<String> check) { |
| 5157 Label materialize_true, materialize_false; | 5127 Label materialize_true, materialize_false; |
| 5158 Label* if_true = NULL; | 5128 Label* if_true = NULL; |
| 5159 Label* if_false = NULL; | 5129 Label* if_false = NULL; |
| 5160 Label* fall_through = NULL; | 5130 Label* fall_through = NULL; |
| 5161 context()->PrepareTest(&materialize_true, &materialize_false, | 5131 context()->PrepareTest(&materialize_true, &materialize_false, |
| 5162 &if_true, &if_false, &fall_through); | 5132 &if_true, &if_false, &fall_through); |
| 5163 | 5133 |
| (...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5513 Assembler::target_address_at(call_target_address, | 5483 Assembler::target_address_at(call_target_address, |
| 5514 unoptimized_code)); | 5484 unoptimized_code)); |
| 5515 return OSR_AFTER_STACK_CHECK; | 5485 return OSR_AFTER_STACK_CHECK; |
| 5516 } | 5486 } |
| 5517 | 5487 |
| 5518 | 5488 |
| 5519 } // namespace internal | 5489 } // namespace internal |
| 5520 } // namespace v8 | 5490 } // namespace v8 |
| 5521 | 5491 |
| 5522 #endif // V8_TARGET_ARCH_X64 | 5492 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |