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_IA32 | 7 #if V8_TARGET_ARCH_IA32 |
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 1326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1337 __ j(equal, &fast, Label::kNear); | 1337 __ j(equal, &fast, Label::kNear); |
1338 // Check that extension is NULL. | 1338 // Check that extension is NULL. |
1339 __ cmp(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0)); | 1339 __ cmp(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0)); |
1340 __ j(not_equal, slow); | 1340 __ j(not_equal, slow); |
1341 // Load next context in chain. | 1341 // Load next context in chain. |
1342 __ mov(temp, ContextOperand(temp, Context::PREVIOUS_INDEX)); | 1342 __ mov(temp, ContextOperand(temp, Context::PREVIOUS_INDEX)); |
1343 __ jmp(&next); | 1343 __ jmp(&next); |
1344 __ bind(&fast); | 1344 __ bind(&fast); |
1345 } | 1345 } |
1346 | 1346 |
1347 // All extension objects were empty and it is safe to use a global | 1347 // All extension objects were empty and it is safe to use a normal global |
1348 // load IC call. | 1348 // load machinery. |
1349 __ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); | 1349 EmitGlobalVariableLoad(proxy, typeof_state); |
1350 __ mov(LoadDescriptor::NameRegister(), proxy->var()->name()); | |
1351 __ mov(LoadDescriptor::SlotRegister(), | |
1352 Immediate(SmiFromSlot(proxy->VariableFeedbackSlot()))); | |
1353 | |
1354 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) | |
1355 ? NOT_CONTEXTUAL | |
1356 : CONTEXTUAL; | |
1357 | |
1358 CallLoadIC(mode); | |
1359 } | 1350 } |
1360 | 1351 |
1361 | 1352 |
1362 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1353 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
1363 Label* slow) { | 1354 Label* slow) { |
1364 DCHECK(var->IsContextSlot()); | 1355 DCHECK(var->IsContextSlot()); |
1365 Register context = esi; | 1356 Register context = esi; |
1366 Register temp = ebx; | 1357 Register temp = ebx; |
1367 | 1358 |
1368 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { | 1359 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1414 } else { // LET || CONST | 1405 } else { // LET || CONST |
1415 __ push(Immediate(var->name())); | 1406 __ push(Immediate(var->name())); |
1416 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1407 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
1417 } | 1408 } |
1418 } | 1409 } |
1419 __ jmp(done); | 1410 __ jmp(done); |
1420 } | 1411 } |
1421 } | 1412 } |
1422 | 1413 |
1423 | 1414 |
1424 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { | 1415 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, |
| 1416 TypeofState typeof_state) { |
| 1417 Variable* var = proxy->var(); |
| 1418 DCHECK(var->IsUnallocatedOrGlobalSlot() || |
| 1419 (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL)); |
| 1420 __ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); |
| 1421 __ mov(LoadDescriptor::NameRegister(), var->name()); |
| 1422 __ mov(LoadDescriptor::SlotRegister(), |
| 1423 Immediate(SmiFromSlot(proxy->VariableFeedbackSlot()))); |
| 1424 // Inside typeof use a regular load, not a contextual load, to avoid |
| 1425 // a reference error. |
| 1426 CallLoadIC(typeof_state == NOT_INSIDE_TYPEOF ? CONTEXTUAL : NOT_CONTEXTUAL); |
| 1427 } |
| 1428 |
| 1429 |
| 1430 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, |
| 1431 TypeofState typeof_state) { |
1425 SetExpressionPosition(proxy); | 1432 SetExpressionPosition(proxy); |
1426 PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS); | 1433 PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS); |
1427 Variable* var = proxy->var(); | 1434 Variable* var = proxy->var(); |
1428 | 1435 |
1429 // Three cases: global variables, lookup variables, and all other types of | 1436 // Three cases: global variables, lookup variables, and all other types of |
1430 // variables. | 1437 // variables. |
1431 switch (var->location()) { | 1438 switch (var->location()) { |
1432 case VariableLocation::GLOBAL: | 1439 case VariableLocation::GLOBAL: |
1433 case VariableLocation::UNALLOCATED: { | 1440 case VariableLocation::UNALLOCATED: { |
1434 Comment cmnt(masm_, "[ Global variable"); | 1441 Comment cmnt(masm_, "[ Global variable"); |
1435 __ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); | 1442 EmitGlobalVariableLoad(proxy, typeof_state); |
1436 __ mov(LoadDescriptor::NameRegister(), var->name()); | |
1437 __ mov(LoadDescriptor::SlotRegister(), | |
1438 Immediate(SmiFromSlot(proxy->VariableFeedbackSlot()))); | |
1439 CallGlobalLoadIC(var->name()); | |
1440 context()->Plug(eax); | 1443 context()->Plug(eax); |
1441 break; | 1444 break; |
1442 } | 1445 } |
1443 | 1446 |
1444 case VariableLocation::PARAMETER: | 1447 case VariableLocation::PARAMETER: |
1445 case VariableLocation::LOCAL: | 1448 case VariableLocation::LOCAL: |
1446 case VariableLocation::CONTEXT: { | 1449 case VariableLocation::CONTEXT: { |
| 1450 DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_state); |
1447 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" | 1451 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" |
1448 : "[ Stack variable"); | 1452 : "[ Stack variable"); |
1449 if (var->binding_needs_init()) { | 1453 if (var->binding_needs_init()) { |
1450 // var->scope() may be NULL when the proxy is located in eval code and | 1454 // var->scope() may be NULL when the proxy is located in eval code and |
1451 // refers to a potential outside binding. Currently those bindings are | 1455 // refers to a potential outside binding. Currently those bindings are |
1452 // always looked up dynamically, i.e. in that case | 1456 // always looked up dynamically, i.e. in that case |
1453 // var->location() == LOOKUP. | 1457 // var->location() == LOOKUP. |
1454 // always holds. | 1458 // always holds. |
1455 DCHECK(var->scope() != NULL); | 1459 DCHECK(var->scope() != NULL); |
1456 | 1460 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1509 } | 1513 } |
1510 context()->Plug(var); | 1514 context()->Plug(var); |
1511 break; | 1515 break; |
1512 } | 1516 } |
1513 | 1517 |
1514 case VariableLocation::LOOKUP: { | 1518 case VariableLocation::LOOKUP: { |
1515 Comment cmnt(masm_, "[ Lookup variable"); | 1519 Comment cmnt(masm_, "[ Lookup variable"); |
1516 Label done, slow; | 1520 Label done, slow; |
1517 // Generate code for loading from variables potentially shadowed | 1521 // Generate code for loading from variables potentially shadowed |
1518 // by eval-introduced variables. | 1522 // by eval-introduced variables. |
1519 EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done); | 1523 EmitDynamicLookupFastCase(proxy, typeof_state, &slow, &done); |
1520 __ bind(&slow); | 1524 __ bind(&slow); |
1521 __ push(esi); // Context. | 1525 __ push(esi); // Context. |
1522 __ push(Immediate(var->name())); | 1526 __ push(Immediate(var->name())); |
1523 __ CallRuntime(Runtime::kLoadLookupSlot, 2); | 1527 Runtime::FunctionId function_id = |
| 1528 typeof_state == NOT_INSIDE_TYPEOF |
| 1529 ? Runtime::kLoadLookupSlot |
| 1530 : Runtime::kLoadLookupSlotNoReferenceError; |
| 1531 __ CallRuntime(function_id, 2); |
1524 __ bind(&done); | 1532 __ bind(&done); |
1525 context()->Plug(eax); | 1533 context()->Plug(eax); |
1526 break; | 1534 break; |
1527 } | 1535 } |
1528 } | 1536 } |
1529 } | 1537 } |
1530 | 1538 |
1531 | 1539 |
1532 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1540 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
1533 Comment cmnt(masm_, "[ RegExpLiteral"); | 1541 Comment cmnt(masm_, "[ RegExpLiteral"); |
(...skipping 3551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5085 } | 5093 } |
5086 } else { | 5094 } else { |
5087 context()->Plug(eax); | 5095 context()->Plug(eax); |
5088 } | 5096 } |
5089 break; | 5097 break; |
5090 } | 5098 } |
5091 } | 5099 } |
5092 } | 5100 } |
5093 | 5101 |
5094 | 5102 |
5095 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | |
5096 VariableProxy* proxy = expr->AsVariableProxy(); | |
5097 DCHECK(!context()->IsEffect()); | |
5098 DCHECK(!context()->IsTest()); | |
5099 | |
5100 if (proxy != NULL && proxy->var()->IsUnallocatedOrGlobalSlot()) { | |
5101 Comment cmnt(masm_, "[ Global variable"); | |
5102 __ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); | |
5103 __ mov(LoadDescriptor::NameRegister(), Immediate(proxy->name())); | |
5104 __ mov(LoadDescriptor::SlotRegister(), | |
5105 Immediate(SmiFromSlot(proxy->VariableFeedbackSlot()))); | |
5106 // Use a regular load, not a contextual load, to avoid a reference | |
5107 // error. | |
5108 CallLoadIC(NOT_CONTEXTUAL); | |
5109 PrepareForBailout(expr, TOS_REG); | |
5110 context()->Plug(eax); | |
5111 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { | |
5112 Comment cmnt(masm_, "[ Lookup slot"); | |
5113 Label done, slow; | |
5114 | |
5115 // Generate code for loading from variables potentially shadowed | |
5116 // by eval-introduced variables. | |
5117 EmitDynamicLookupFastCase(proxy, INSIDE_TYPEOF, &slow, &done); | |
5118 | |
5119 __ bind(&slow); | |
5120 __ push(esi); | |
5121 __ push(Immediate(proxy->name())); | |
5122 __ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2); | |
5123 PrepareForBailout(expr, TOS_REG); | |
5124 __ bind(&done); | |
5125 | |
5126 context()->Plug(eax); | |
5127 } else { | |
5128 // This expression cannot throw a reference error at the top level. | |
5129 VisitInDuplicateContext(expr); | |
5130 } | |
5131 } | |
5132 | |
5133 | |
5134 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, | 5103 void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, |
5135 Expression* sub_expr, | 5104 Expression* sub_expr, |
5136 Handle<String> check) { | 5105 Handle<String> check) { |
5137 Label materialize_true, materialize_false; | 5106 Label materialize_true, materialize_false; |
5138 Label* if_true = NULL; | 5107 Label* if_true = NULL; |
5139 Label* if_false = NULL; | 5108 Label* if_false = NULL; |
5140 Label* fall_through = NULL; | 5109 Label* fall_through = NULL; |
5141 context()->PrepareTest(&materialize_true, &materialize_false, | 5110 context()->PrepareTest(&materialize_true, &materialize_false, |
5142 &if_true, &if_false, &fall_through); | 5111 &if_true, &if_false, &fall_through); |
5143 | 5112 |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5492 Assembler::target_address_at(call_target_address, | 5461 Assembler::target_address_at(call_target_address, |
5493 unoptimized_code)); | 5462 unoptimized_code)); |
5494 return OSR_AFTER_STACK_CHECK; | 5463 return OSR_AFTER_STACK_CHECK; |
5495 } | 5464 } |
5496 | 5465 |
5497 | 5466 |
5498 } // namespace internal | 5467 } // namespace internal |
5499 } // namespace v8 | 5468 } // namespace v8 |
5500 | 5469 |
5501 #endif // V8_TARGET_ARCH_IA32 | 5470 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |