| 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 |