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