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_X87 | 7 #if V8_TARGET_ARCH_X87 |
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 1319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1330 __ j(equal, &fast, Label::kNear); | 1330 __ j(equal, &fast, Label::kNear); |
1331 // Check that extension is NULL. | 1331 // Check that extension is NULL. |
1332 __ cmp(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0)); | 1332 __ cmp(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0)); |
1333 __ j(not_equal, slow); | 1333 __ j(not_equal, slow); |
1334 // Load next context in chain. | 1334 // Load next context in chain. |
1335 __ mov(temp, ContextOperand(temp, Context::PREVIOUS_INDEX)); | 1335 __ mov(temp, ContextOperand(temp, Context::PREVIOUS_INDEX)); |
1336 __ jmp(&next); | 1336 __ jmp(&next); |
1337 __ bind(&fast); | 1337 __ bind(&fast); |
1338 } | 1338 } |
1339 | 1339 |
1340 // All extension objects were empty and it is safe to use a global | 1340 // All extension objects were empty and it is safe to use a normal global |
1341 // load IC call. | 1341 // load machinery. |
1342 __ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); | 1342 EmitGlobalVariableLoad(proxy, typeof_state); |
1343 __ mov(LoadDescriptor::NameRegister(), proxy->var()->name()); | |
1344 __ mov(LoadDescriptor::SlotRegister(), | |
1345 Immediate(SmiFromSlot(proxy->VariableFeedbackSlot()))); | |
1346 | |
1347 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) | |
1348 ? NOT_CONTEXTUAL | |
1349 : CONTEXTUAL; | |
1350 | |
1351 CallLoadIC(mode); | |
1352 } | 1343 } |
1353 | 1344 |
1354 | 1345 |
1355 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1346 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
1356 Label* slow) { | 1347 Label* slow) { |
1357 DCHECK(var->IsContextSlot()); | 1348 DCHECK(var->IsContextSlot()); |
1358 Register context = esi; | 1349 Register context = esi; |
1359 Register temp = ebx; | 1350 Register temp = ebx; |
1360 | 1351 |
1361 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { | 1352 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1407 } else { // LET || CONST | 1398 } else { // LET || CONST |
1408 __ push(Immediate(var->name())); | 1399 __ push(Immediate(var->name())); |
1409 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1400 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
1410 } | 1401 } |
1411 } | 1402 } |
1412 __ jmp(done); | 1403 __ jmp(done); |
1413 } | 1404 } |
1414 } | 1405 } |
1415 | 1406 |
1416 | 1407 |
1417 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { | 1408 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, |
| 1409 TypeofState typeof_state) { |
| 1410 Variable* var = proxy->var(); |
| 1411 DCHECK(var->IsUnallocatedOrGlobalSlot() || |
| 1412 (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL)); |
| 1413 __ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); |
| 1414 __ mov(LoadDescriptor::NameRegister(), var->name()); |
| 1415 __ mov(LoadDescriptor::SlotRegister(), |
| 1416 Immediate(SmiFromSlot(proxy->VariableFeedbackSlot()))); |
| 1417 // Inside typeof use a regular load, not a contextual load, to avoid |
| 1418 // a reference error. |
| 1419 CallLoadIC(typeof_state == NOT_INSIDE_TYPEOF ? CONTEXTUAL : NOT_CONTEXTUAL); |
| 1420 } |
| 1421 |
| 1422 |
| 1423 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, |
| 1424 TypeofState typeof_state) { |
1418 SetExpressionPosition(proxy); | 1425 SetExpressionPosition(proxy); |
1419 PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS); | 1426 PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS); |
1420 Variable* var = proxy->var(); | 1427 Variable* var = proxy->var(); |
1421 | 1428 |
1422 // Three cases: global variables, lookup variables, and all other types of | 1429 // Three cases: global variables, lookup variables, and all other types of |
1423 // variables. | 1430 // variables. |
1424 switch (var->location()) { | 1431 switch (var->location()) { |
1425 case VariableLocation::GLOBAL: | 1432 case VariableLocation::GLOBAL: |
1426 case VariableLocation::UNALLOCATED: { | 1433 case VariableLocation::UNALLOCATED: { |
1427 Comment cmnt(masm_, "[ Global variable"); | 1434 Comment cmnt(masm_, "[ Global variable"); |
1428 __ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); | 1435 EmitGlobalVariableLoad(proxy, typeof_state); |
1429 __ mov(LoadDescriptor::NameRegister(), var->name()); | |
1430 __ mov(LoadDescriptor::SlotRegister(), | |
1431 Immediate(SmiFromSlot(proxy->VariableFeedbackSlot()))); | |
1432 CallGlobalLoadIC(var->name()); | |
1433 context()->Plug(eax); | 1436 context()->Plug(eax); |
1434 break; | 1437 break; |
1435 } | 1438 } |
1436 | 1439 |
1437 case VariableLocation::PARAMETER: | 1440 case VariableLocation::PARAMETER: |
1438 case VariableLocation::LOCAL: | 1441 case VariableLocation::LOCAL: |
1439 case VariableLocation::CONTEXT: { | 1442 case VariableLocation::CONTEXT: { |
| 1443 DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_state); |
1440 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" | 1444 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" |
1441 : "[ Stack variable"); | 1445 : "[ Stack variable"); |
1442 if (var->binding_needs_init()) { | 1446 if (var->binding_needs_init()) { |
1443 // var->scope() may be NULL when the proxy is located in eval code and | 1447 // var->scope() may be NULL when the proxy is located in eval code and |
1444 // refers to a potential outside binding. Currently those bindings are | 1448 // refers to a potential outside binding. Currently those bindings are |
1445 // always looked up dynamically, i.e. in that case | 1449 // always looked up dynamically, i.e. in that case |
1446 // var->location() == LOOKUP. | 1450 // var->location() == LOOKUP. |
1447 // always holds. | 1451 // always holds. |
1448 DCHECK(var->scope() != NULL); | 1452 DCHECK(var->scope() != NULL); |
1449 | 1453 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1502 } | 1506 } |
1503 context()->Plug(var); | 1507 context()->Plug(var); |
1504 break; | 1508 break; |
1505 } | 1509 } |
1506 | 1510 |
1507 case VariableLocation::LOOKUP: { | 1511 case VariableLocation::LOOKUP: { |
1508 Comment cmnt(masm_, "[ Lookup variable"); | 1512 Comment cmnt(masm_, "[ Lookup variable"); |
1509 Label done, slow; | 1513 Label done, slow; |
1510 // Generate code for loading from variables potentially shadowed | 1514 // Generate code for loading from variables potentially shadowed |
1511 // by eval-introduced variables. | 1515 // by eval-introduced variables. |
1512 EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done); | 1516 EmitDynamicLookupFastCase(proxy, typeof_state, &slow, &done); |
1513 __ bind(&slow); | 1517 __ bind(&slow); |
1514 __ push(esi); // Context. | 1518 __ push(esi); // Context. |
1515 __ push(Immediate(var->name())); | 1519 __ push(Immediate(var->name())); |
1516 __ CallRuntime(Runtime::kLoadLookupSlot, 2); | 1520 Runtime::FunctionId function_id = |
| 1521 typeof_state == NOT_INSIDE_TYPEOF |
| 1522 ? Runtime::kLoadLookupSlot |
| 1523 : Runtime::kLoadLookupSlotNoReferenceError; |
| 1524 __ CallRuntime(function_id, 2); |
1517 __ bind(&done); | 1525 __ bind(&done); |
1518 context()->Plug(eax); | 1526 context()->Plug(eax); |
1519 break; | 1527 break; |
1520 } | 1528 } |
1521 } | 1529 } |
1522 } | 1530 } |
1523 | 1531 |
1524 | 1532 |
1525 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1533 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
1526 Comment cmnt(masm_, "[ RegExpLiteral"); | 1534 Comment cmnt(masm_, "[ RegExpLiteral"); |
(...skipping 3548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5075 } | 5083 } |
5076 } else { | 5084 } else { |
5077 context()->Plug(eax); | 5085 context()->Plug(eax); |
5078 } | 5086 } |
5079 break; | 5087 break; |
5080 } | 5088 } |
5081 } | 5089 } |
5082 } | 5090 } |
5083 | 5091 |
5084 | 5092 |
5085 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | |
5086 VariableProxy* proxy = expr->AsVariableProxy(); | |
5087 DCHECK(!context()->IsEffect()); | |
5088 DCHECK(!context()->IsTest()); | |
5089 | |
5090 if (proxy != NULL && proxy->var()->IsUnallocatedOrGlobalSlot()) { | |
5091 Comment cmnt(masm_, "[ Global variable"); | |
5092 __ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); | |
5093 __ mov(LoadDescriptor::NameRegister(), Immediate(proxy->name())); | |
5094 __ mov(LoadDescriptor::SlotRegister(), | |
5095 Immediate(SmiFromSlot(proxy->VariableFeedbackSlot()))); | |
5096 // Use a regular load, not a contextual load, to avoid a reference | |
5097 // error. | |
5098 CallLoadIC(NOT_CONTEXTUAL); | |
5099 PrepareForBailout(expr, TOS_REG); | |
5100 context()->Plug(eax); | |
5101 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { | |
5102 Comment cmnt(masm_, "[ Lookup slot"); | |
5103 Label done, slow; | |
5104 | |
5105 // Generate code for loading from variables potentially shadowed | |
5106 // by eval-introduced variables. | |
5107 EmitDynamicLookupFastCase(proxy, INSIDE_TYPEOF, &slow, &done); | |
5108 | |
5109 __ bind(&slow); | |
5110 __ push(esi); | |
5111 __ push(Immediate(proxy->name())); | |
5112 __ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2); | |
5113 PrepareForBailout(expr, TOS_REG); | |
5114 __ bind(&done); | |
5115 | |
5116 context()->Plug(eax); | |
5117 } else { | |
5118 // This expression cannot throw a reference error at the top level. | |
5119 VisitInDuplicateContext(expr); | |
5120 } | |
5121 } | |
5122 | |
5123 | |
5124 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, | 5093 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, |
5125 Expression* sub_expr, | 5094 Expression* sub_expr, |
5126 Handle<String> check) { | 5095 Handle<String> check) { |
5127 Label materialize_true, materialize_false; | 5096 Label materialize_true, materialize_false; |
5128 Label* if_true = NULL; | 5097 Label* if_true = NULL; |
5129 Label* if_false = NULL; | 5098 Label* if_false = NULL; |
5130 Label* fall_through = NULL; | 5099 Label* fall_through = NULL; |
5131 context()->PrepareTest(&materialize_true, &materialize_false, | 5100 context()->PrepareTest(&materialize_true, &materialize_false, |
5132 &if_true, &if_false, &fall_through); | 5101 &if_true, &if_false, &fall_through); |
5133 | 5102 |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5482 Assembler::target_address_at(call_target_address, | 5451 Assembler::target_address_at(call_target_address, |
5483 unoptimized_code)); | 5452 unoptimized_code)); |
5484 return OSR_AFTER_STACK_CHECK; | 5453 return OSR_AFTER_STACK_CHECK; |
5485 } | 5454 } |
5486 | 5455 |
5487 | 5456 |
5488 } // namespace internal | 5457 } // namespace internal |
5489 } // namespace v8 | 5458 } // namespace v8 |
5490 | 5459 |
5491 #endif // V8_TARGET_ARCH_X87 | 5460 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |