OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 620 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
631 if (false_label_ != fall_through_) __ jmp(false_label_); | 631 if (false_label_ != fall_through_) __ jmp(false_label_); |
632 } | 632 } |
633 } | 633 } |
634 | 634 |
635 | 635 |
636 void FullCodeGenerator::DoTest(Expression* condition, | 636 void FullCodeGenerator::DoTest(Expression* condition, |
637 Label* if_true, | 637 Label* if_true, |
638 Label* if_false, | 638 Label* if_false, |
639 Label* fall_through) { | 639 Label* fall_through) { |
640 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); | 640 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); |
641 CallIC(ic, RelocInfo::CODE_TARGET, condition->test_id()); | 641 CallIC(ic, NOT_CONTEXTUAL, condition->test_id()); |
642 __ test(result_register(), result_register()); | 642 __ test(result_register(), result_register()); |
643 // The stub returns nonzero for true. | 643 // The stub returns nonzero for true. |
644 Split(not_zero, if_true, if_false, fall_through); | 644 Split(not_zero, if_true, if_false, fall_through); |
645 } | 645 } |
646 | 646 |
647 | 647 |
648 void FullCodeGenerator::Split(Condition cc, | 648 void FullCodeGenerator::Split(Condition cc, |
649 Label* if_true, | 649 Label* if_true, |
650 Label* if_false, | 650 Label* if_false, |
651 Label* fall_through) { | 651 Label* fall_through) { |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
982 __ cmp(edx, eax); | 982 __ cmp(edx, eax); |
983 __ j(not_equal, &next_test); | 983 __ j(not_equal, &next_test); |
984 __ Drop(1); // Switch value is no longer needed. | 984 __ Drop(1); // Switch value is no longer needed. |
985 __ jmp(clause->body_target()); | 985 __ jmp(clause->body_target()); |
986 __ bind(&slow_case); | 986 __ bind(&slow_case); |
987 } | 987 } |
988 | 988 |
989 // Record position before stub call for type feedback. | 989 // Record position before stub call for type feedback. |
990 SetSourcePosition(clause->position()); | 990 SetSourcePosition(clause->position()); |
991 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); | 991 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); |
992 CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId()); | 992 CallIC(ic, NOT_CONTEXTUAL, clause->CompareId()); |
993 patch_site.EmitPatchInfo(); | 993 patch_site.EmitPatchInfo(); |
994 __ test(eax, eax); | 994 __ test(eax, eax); |
995 __ j(not_equal, &next_test); | 995 __ j(not_equal, &next_test); |
996 __ Drop(1); // Switch value is no longer needed. | 996 __ Drop(1); // Switch value is no longer needed. |
997 __ jmp(clause->body_target()); | 997 __ jmp(clause->body_target()); |
998 } | 998 } |
999 | 999 |
1000 // Discard the test value and jump to the default if present, otherwise to | 1000 // Discard the test value and jump to the default if present, otherwise to |
1001 // the end of the statement. | 1001 // the end of the statement. |
1002 __ bind(&next_test); | 1002 __ bind(&next_test); |
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1328 // Load next context in chain. | 1328 // Load next context in chain. |
1329 __ mov(temp, ContextOperand(temp, Context::PREVIOUS_INDEX)); | 1329 __ mov(temp, ContextOperand(temp, Context::PREVIOUS_INDEX)); |
1330 __ jmp(&next); | 1330 __ jmp(&next); |
1331 __ bind(&fast); | 1331 __ bind(&fast); |
1332 } | 1332 } |
1333 | 1333 |
1334 // All extension objects were empty and it is safe to use a global | 1334 // All extension objects were empty and it is safe to use a global |
1335 // load IC call. | 1335 // load IC call. |
1336 __ mov(edx, GlobalObjectOperand()); | 1336 __ mov(edx, GlobalObjectOperand()); |
1337 __ mov(ecx, var->name()); | 1337 __ mov(ecx, var->name()); |
1338 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1338 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) |
1339 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) | 1339 ? NOT_CONTEXTUAL |
1340 ? RelocInfo::CODE_TARGET | 1340 : CONTEXTUAL; |
1341 : RelocInfo::CODE_TARGET_CONTEXT; | 1341 |
| 1342 Handle<Code> ic = mode == CONTEXTUAL |
| 1343 ? isolate()->builtins()->LoadIC_Initialize_Contextual() |
| 1344 : isolate()->builtins()->LoadIC_Initialize(); |
1342 CallIC(ic, mode); | 1345 CallIC(ic, mode); |
1343 } | 1346 } |
1344 | 1347 |
1345 | 1348 |
1346 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1349 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
1347 Label* slow) { | 1350 Label* slow) { |
1348 ASSERT(var->IsContextSlot()); | 1351 ASSERT(var->IsContextSlot()); |
1349 Register context = esi; | 1352 Register context = esi; |
1350 Register temp = ebx; | 1353 Register temp = ebx; |
1351 | 1354 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1412 | 1415 |
1413 // Three cases: global variables, lookup variables, and all other types of | 1416 // Three cases: global variables, lookup variables, and all other types of |
1414 // variables. | 1417 // variables. |
1415 switch (var->location()) { | 1418 switch (var->location()) { |
1416 case Variable::UNALLOCATED: { | 1419 case Variable::UNALLOCATED: { |
1417 Comment cmnt(masm_, "Global variable"); | 1420 Comment cmnt(masm_, "Global variable"); |
1418 // Use inline caching. Variable name is passed in ecx and the global | 1421 // Use inline caching. Variable name is passed in ecx and the global |
1419 // object in eax. | 1422 // object in eax. |
1420 __ mov(edx, GlobalObjectOperand()); | 1423 __ mov(edx, GlobalObjectOperand()); |
1421 __ mov(ecx, var->name()); | 1424 __ mov(ecx, var->name()); |
1422 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1425 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize_Contextual(); |
1423 CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1426 CallIC(ic, CONTEXTUAL); |
1424 context()->Plug(eax); | 1427 context()->Plug(eax); |
1425 break; | 1428 break; |
1426 } | 1429 } |
1427 | 1430 |
1428 case Variable::PARAMETER: | 1431 case Variable::PARAMETER: |
1429 case Variable::LOCAL: | 1432 case Variable::LOCAL: |
1430 case Variable::CONTEXT: { | 1433 case Variable::CONTEXT: { |
1431 Comment cmnt(masm_, var->IsContextSlot() | 1434 Comment cmnt(masm_, var->IsContextSlot() |
1432 ? "Context variable" | 1435 ? "Context variable" |
1433 : "Stack variable"); | 1436 : "Stack variable"); |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1632 // Fall through. | 1635 // Fall through. |
1633 case ObjectLiteral::Property::COMPUTED: | 1636 case ObjectLiteral::Property::COMPUTED: |
1634 if (key->value()->IsInternalizedString()) { | 1637 if (key->value()->IsInternalizedString()) { |
1635 if (property->emit_store()) { | 1638 if (property->emit_store()) { |
1636 VisitForAccumulatorValue(value); | 1639 VisitForAccumulatorValue(value); |
1637 __ mov(ecx, Immediate(key->value())); | 1640 __ mov(ecx, Immediate(key->value())); |
1638 __ mov(edx, Operand(esp, 0)); | 1641 __ mov(edx, Operand(esp, 0)); |
1639 Handle<Code> ic = is_classic_mode() | 1642 Handle<Code> ic = is_classic_mode() |
1640 ? isolate()->builtins()->StoreIC_Initialize() | 1643 ? isolate()->builtins()->StoreIC_Initialize() |
1641 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 1644 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
1642 CallIC(ic, RelocInfo::CODE_TARGET, key->LiteralFeedbackId()); | 1645 CallIC(ic, NOT_CONTEXTUAL, key->LiteralFeedbackId()); |
1643 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1646 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
1644 } else { | 1647 } else { |
1645 VisitForEffect(value); | 1648 VisitForEffect(value); |
1646 } | 1649 } |
1647 break; | 1650 break; |
1648 } | 1651 } |
1649 __ push(Operand(esp, 0)); // Duplicate receiver. | 1652 __ push(Operand(esp, 0)); // Duplicate receiver. |
1650 VisitForStackValue(key); | 1653 VisitForStackValue(key); |
1651 VisitForStackValue(value); | 1654 VisitForStackValue(value); |
1652 if (property->emit_store()) { | 1655 if (property->emit_store()) { |
(...skipping 558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2211 ecx, edx, kDontSaveFPRegs); | 2214 ecx, edx, kDontSaveFPRegs); |
2212 } | 2215 } |
2213 | 2216 |
2214 | 2217 |
2215 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 2218 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
2216 SetSourcePosition(prop->position()); | 2219 SetSourcePosition(prop->position()); |
2217 Literal* key = prop->key()->AsLiteral(); | 2220 Literal* key = prop->key()->AsLiteral(); |
2218 ASSERT(!key->value()->IsSmi()); | 2221 ASSERT(!key->value()->IsSmi()); |
2219 __ mov(ecx, Immediate(key->value())); | 2222 __ mov(ecx, Immediate(key->value())); |
2220 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2223 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
2221 CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); | 2224 CallIC(ic, NOT_CONTEXTUAL, prop->PropertyFeedbackId()); |
2222 } | 2225 } |
2223 | 2226 |
2224 | 2227 |
2225 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 2228 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
2226 SetSourcePosition(prop->position()); | 2229 SetSourcePosition(prop->position()); |
2227 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2230 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
2228 CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); | 2231 CallIC(ic, NOT_CONTEXTUAL, prop->PropertyFeedbackId()); |
2229 } | 2232 } |
2230 | 2233 |
2231 | 2234 |
2232 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 2235 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
2233 Token::Value op, | 2236 Token::Value op, |
2234 OverwriteMode mode, | 2237 OverwriteMode mode, |
2235 Expression* left, | 2238 Expression* left, |
2236 Expression* right) { | 2239 Expression* right) { |
2237 // Do combined smi check of the operands. Left operand is on the | 2240 // Do combined smi check of the operands. Left operand is on the |
2238 // stack. Right operand is in eax. | 2241 // stack. Right operand is in eax. |
2239 Label smi_case, done, stub_call; | 2242 Label smi_case, done, stub_call; |
2240 __ pop(edx); | 2243 __ pop(edx); |
2241 __ mov(ecx, eax); | 2244 __ mov(ecx, eax); |
2242 __ or_(eax, edx); | 2245 __ or_(eax, edx); |
2243 JumpPatchSite patch_site(masm_); | 2246 JumpPatchSite patch_site(masm_); |
2244 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear); | 2247 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear); |
2245 | 2248 |
2246 __ bind(&stub_call); | 2249 __ bind(&stub_call); |
2247 __ mov(eax, ecx); | 2250 __ mov(eax, ecx); |
2248 BinaryOpStub stub(op, mode); | 2251 BinaryOpStub stub(op, mode); |
2249 CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, | 2252 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, |
2250 expr->BinaryOperationFeedbackId()); | 2253 expr->BinaryOperationFeedbackId()); |
2251 patch_site.EmitPatchInfo(); | 2254 patch_site.EmitPatchInfo(); |
2252 __ jmp(&done, Label::kNear); | 2255 __ jmp(&done, Label::kNear); |
2253 | 2256 |
2254 // Smi case. | 2257 // Smi case. |
2255 __ bind(&smi_case); | 2258 __ bind(&smi_case); |
2256 __ mov(eax, edx); // Copy left operand in case of a stub call. | 2259 __ mov(eax, edx); // Copy left operand in case of a stub call. |
2257 | 2260 |
2258 switch (op) { | 2261 switch (op) { |
2259 case Token::SAR: | 2262 case Token::SAR: |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2325 context()->Plug(eax); | 2328 context()->Plug(eax); |
2326 } | 2329 } |
2327 | 2330 |
2328 | 2331 |
2329 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, | 2332 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, |
2330 Token::Value op, | 2333 Token::Value op, |
2331 OverwriteMode mode) { | 2334 OverwriteMode mode) { |
2332 __ pop(edx); | 2335 __ pop(edx); |
2333 BinaryOpStub stub(op, mode); | 2336 BinaryOpStub stub(op, mode); |
2334 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 2337 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
2335 CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, | 2338 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, |
2336 expr->BinaryOperationFeedbackId()); | 2339 expr->BinaryOperationFeedbackId()); |
2337 patch_site.EmitPatchInfo(); | 2340 patch_site.EmitPatchInfo(); |
2338 context()->Plug(eax); | 2341 context()->Plug(eax); |
2339 } | 2342 } |
2340 | 2343 |
2341 | 2344 |
2342 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 2345 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
2343 // Invalid left-hand sides are rewritten by the parser to have a 'throw | 2346 // Invalid left-hand sides are rewritten by the parser to have a 'throw |
2344 // ReferenceError' on the left-hand side. | 2347 // ReferenceError' on the left-hand side. |
2345 if (!expr->IsValidLeftHandSide()) { | 2348 if (!expr->IsValidLeftHandSide()) { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2396 | 2399 |
2397 | 2400 |
2398 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 2401 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
2399 Token::Value op) { | 2402 Token::Value op) { |
2400 if (var->IsUnallocated()) { | 2403 if (var->IsUnallocated()) { |
2401 // Global var, const, or let. | 2404 // Global var, const, or let. |
2402 __ mov(ecx, var->name()); | 2405 __ mov(ecx, var->name()); |
2403 __ mov(edx, GlobalObjectOperand()); | 2406 __ mov(edx, GlobalObjectOperand()); |
2404 Handle<Code> ic = is_classic_mode() | 2407 Handle<Code> ic = is_classic_mode() |
2405 ? isolate()->builtins()->StoreIC_Initialize() | 2408 ? isolate()->builtins()->StoreIC_Initialize() |
2406 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 2409 : isolate()->builtins()->StoreIC_Initialize_Contextual_Strict(); |
2407 CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); | 2410 CallIC(ic, CONTEXTUAL); |
2408 | |
2409 } else if (op == Token::INIT_CONST) { | 2411 } else if (op == Token::INIT_CONST) { |
2410 // Const initializers need a write barrier. | 2412 // Const initializers need a write barrier. |
2411 ASSERT(!var->IsParameter()); // No const parameters. | 2413 ASSERT(!var->IsParameter()); // No const parameters. |
2412 if (var->IsStackLocal()) { | 2414 if (var->IsStackLocal()) { |
2413 Label skip; | 2415 Label skip; |
2414 __ mov(edx, StackOperand(var)); | 2416 __ mov(edx, StackOperand(var)); |
2415 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2417 __ cmp(edx, isolate()->factory()->the_hole_value()); |
2416 __ j(not_equal, &skip); | 2418 __ j(not_equal, &skip); |
2417 __ mov(StackOperand(var), eax); | 2419 __ mov(StackOperand(var), eax); |
2418 __ bind(&skip); | 2420 __ bind(&skip); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2495 ASSERT(prop != NULL); | 2497 ASSERT(prop != NULL); |
2496 ASSERT(prop->key()->AsLiteral() != NULL); | 2498 ASSERT(prop->key()->AsLiteral() != NULL); |
2497 | 2499 |
2498 // Record source code position before IC call. | 2500 // Record source code position before IC call. |
2499 SetSourcePosition(expr->position()); | 2501 SetSourcePosition(expr->position()); |
2500 __ mov(ecx, prop->key()->AsLiteral()->value()); | 2502 __ mov(ecx, prop->key()->AsLiteral()->value()); |
2501 __ pop(edx); | 2503 __ pop(edx); |
2502 Handle<Code> ic = is_classic_mode() | 2504 Handle<Code> ic = is_classic_mode() |
2503 ? isolate()->builtins()->StoreIC_Initialize() | 2505 ? isolate()->builtins()->StoreIC_Initialize() |
2504 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 2506 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
2505 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); | 2507 CallIC(ic, NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); |
2506 | 2508 |
2507 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2509 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
2508 context()->Plug(eax); | 2510 context()->Plug(eax); |
2509 } | 2511 } |
2510 | 2512 |
2511 | 2513 |
2512 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2514 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
2513 // Assignment to a property, using a keyed store IC. | 2515 // Assignment to a property, using a keyed store IC. |
2514 // eax : value | 2516 // eax : value |
2515 // esp[0] : key | 2517 // esp[0] : key |
2516 // esp[kPointerSize] : receiver | 2518 // esp[kPointerSize] : receiver |
2517 | 2519 |
2518 __ pop(ecx); // Key. | 2520 __ pop(ecx); // Key. |
2519 __ pop(edx); | 2521 __ pop(edx); |
2520 // Record source code position before IC call. | 2522 // Record source code position before IC call. |
2521 SetSourcePosition(expr->position()); | 2523 SetSourcePosition(expr->position()); |
2522 Handle<Code> ic = is_classic_mode() | 2524 Handle<Code> ic = is_classic_mode() |
2523 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2525 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
2524 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2526 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
2525 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); | 2527 CallIC(ic, NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); |
2526 | 2528 |
2527 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2529 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
2528 context()->Plug(eax); | 2530 context()->Plug(eax); |
2529 } | 2531 } |
2530 | 2532 |
2531 | 2533 |
2532 void FullCodeGenerator::VisitProperty(Property* expr) { | 2534 void FullCodeGenerator::VisitProperty(Property* expr) { |
2533 Comment cmnt(masm_, "[ Property"); | 2535 Comment cmnt(masm_, "[ Property"); |
2534 Expression* key = expr->key(); | 2536 Expression* key = expr->key(); |
2535 | 2537 |
2536 if (key->IsPropertyName()) { | 2538 if (key->IsPropertyName()) { |
2537 VisitForAccumulatorValue(expr->obj()); | 2539 VisitForAccumulatorValue(expr->obj()); |
2538 __ mov(edx, result_register()); | 2540 __ mov(edx, result_register()); |
2539 EmitNamedPropertyLoad(expr); | 2541 EmitNamedPropertyLoad(expr); |
2540 PrepareForBailoutForId(expr->LoadId(), TOS_REG); | 2542 PrepareForBailoutForId(expr->LoadId(), TOS_REG); |
2541 context()->Plug(eax); | 2543 context()->Plug(eax); |
2542 } else { | 2544 } else { |
2543 VisitForStackValue(expr->obj()); | 2545 VisitForStackValue(expr->obj()); |
2544 VisitForAccumulatorValue(expr->key()); | 2546 VisitForAccumulatorValue(expr->key()); |
2545 __ pop(edx); // Object. | 2547 __ pop(edx); // Object. |
2546 __ mov(ecx, result_register()); // Key. | 2548 __ mov(ecx, result_register()); // Key. |
2547 EmitKeyedPropertyLoad(expr); | 2549 EmitKeyedPropertyLoad(expr); |
2548 context()->Plug(eax); | 2550 context()->Plug(eax); |
2549 } | 2551 } |
2550 } | 2552 } |
2551 | 2553 |
2552 | 2554 |
2553 void FullCodeGenerator::CallIC(Handle<Code> code, | 2555 void FullCodeGenerator::CallIC(Handle<Code> code, |
2554 RelocInfo::Mode rmode, | 2556 ContextualMode mode, |
2555 TypeFeedbackId ast_id) { | 2557 TypeFeedbackId ast_id) { |
2556 ic_total_count_++; | 2558 ic_total_count_++; |
2557 __ call(code, rmode, ast_id); | 2559 ASSERT(mode != CONTEXTUAL || ast_id.IsNone()); |
| 2560 __ call(code, RelocInfo::CODE_TARGET, ast_id); |
2558 } | 2561 } |
2559 | 2562 |
2560 | 2563 |
2561 | 2564 |
2562 | 2565 |
2563 void FullCodeGenerator::EmitCallWithIC(Call* expr, | 2566 void FullCodeGenerator::EmitCallWithIC(Call* expr, |
2564 Handle<Object> name, | 2567 Handle<Object> name, |
2565 RelocInfo::Mode mode) { | 2568 ContextualMode mode) { |
2566 // Code common for calls using the IC. | 2569 // Code common for calls using the IC. |
2567 ZoneList<Expression*>* args = expr->arguments(); | 2570 ZoneList<Expression*>* args = expr->arguments(); |
2568 int arg_count = args->length(); | 2571 int arg_count = args->length(); |
2569 { PreservePositionScope scope(masm()->positions_recorder()); | 2572 { PreservePositionScope scope(masm()->positions_recorder()); |
2570 for (int i = 0; i < arg_count; i++) { | 2573 for (int i = 0; i < arg_count; i++) { |
2571 VisitForStackValue(args->at(i)); | 2574 VisitForStackValue(args->at(i)); |
2572 } | 2575 } |
2573 __ Set(ecx, Immediate(name)); | 2576 __ Set(ecx, Immediate(name)); |
2574 } | 2577 } |
2575 // Record source position of the IC call. | 2578 // Record source position of the IC call. |
2576 SetSourcePosition(expr->position()); | 2579 SetSourcePosition(expr->position()); |
2577 Handle<Code> ic = | 2580 Handle<Code> ic = |
2578 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); | 2581 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); |
2579 CallIC(ic, mode, expr->CallFeedbackId()); | 2582 TypeFeedbackId ast_id = mode == CONTEXTUAL |
| 2583 ? TypeFeedbackId::None() |
| 2584 : expr->CallFeedbackId(); |
| 2585 CallIC(ic, mode, ast_id); |
2580 RecordJSReturnSite(expr); | 2586 RecordJSReturnSite(expr); |
2581 // Restore context register. | 2587 // Restore context register. |
2582 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2588 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
2583 context()->Plug(eax); | 2589 context()->Plug(eax); |
2584 } | 2590 } |
2585 | 2591 |
2586 | 2592 |
2587 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2593 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
2588 Expression* key) { | 2594 Expression* key) { |
2589 // Load the key. | 2595 // Load the key. |
(...skipping 11 matching lines...) Expand all Loading... |
2601 { PreservePositionScope scope(masm()->positions_recorder()); | 2607 { PreservePositionScope scope(masm()->positions_recorder()); |
2602 for (int i = 0; i < arg_count; i++) { | 2608 for (int i = 0; i < arg_count; i++) { |
2603 VisitForStackValue(args->at(i)); | 2609 VisitForStackValue(args->at(i)); |
2604 } | 2610 } |
2605 } | 2611 } |
2606 // Record source position of the IC call. | 2612 // Record source position of the IC call. |
2607 SetSourcePosition(expr->position()); | 2613 SetSourcePosition(expr->position()); |
2608 Handle<Code> ic = | 2614 Handle<Code> ic = |
2609 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); | 2615 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); |
2610 __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. | 2616 __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. |
2611 CallIC(ic, RelocInfo::CODE_TARGET, expr->CallFeedbackId()); | 2617 CallIC(ic, NOT_CONTEXTUAL, expr->CallFeedbackId()); |
2612 RecordJSReturnSite(expr); | 2618 RecordJSReturnSite(expr); |
2613 // Restore context register. | 2619 // Restore context register. |
2614 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2620 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
2615 context()->DropAndPlug(1, eax); // Drop the key still on the stack. | 2621 context()->DropAndPlug(1, eax); // Drop the key still on the stack. |
2616 } | 2622 } |
2617 | 2623 |
2618 | 2624 |
2619 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { | 2625 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { |
2620 // Code common for calls using the call stub. | 2626 // Code common for calls using the call stub. |
2621 ZoneList<Expression*>* args = expr->arguments(); | 2627 ZoneList<Expression*>* args = expr->arguments(); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2711 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); | 2717 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); |
2712 __ CallStub(&stub); | 2718 __ CallStub(&stub); |
2713 RecordJSReturnSite(expr); | 2719 RecordJSReturnSite(expr); |
2714 // Restore context register. | 2720 // Restore context register. |
2715 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2721 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
2716 context()->DropAndPlug(1, eax); | 2722 context()->DropAndPlug(1, eax); |
2717 | 2723 |
2718 } else if (proxy != NULL && proxy->var()->IsUnallocated()) { | 2724 } else if (proxy != NULL && proxy->var()->IsUnallocated()) { |
2719 // Push global object as receiver for the call IC. | 2725 // Push global object as receiver for the call IC. |
2720 __ push(GlobalObjectOperand()); | 2726 __ push(GlobalObjectOperand()); |
2721 EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT); | 2727 EmitCallWithIC(expr, proxy->name(), CONTEXTUAL); |
2722 | |
2723 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { | 2728 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { |
2724 // Call to a lookup slot (dynamically introduced variable). | 2729 // Call to a lookup slot (dynamically introduced variable). |
2725 Label slow, done; | 2730 Label slow, done; |
2726 { PreservePositionScope scope(masm()->positions_recorder()); | 2731 { PreservePositionScope scope(masm()->positions_recorder()); |
2727 // Generate code for loading from variables potentially shadowed by | 2732 // Generate code for loading from variables potentially shadowed by |
2728 // eval-introduced variables. | 2733 // eval-introduced variables. |
2729 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); | 2734 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); |
2730 } | 2735 } |
2731 __ bind(&slow); | 2736 __ bind(&slow); |
2732 // Call the runtime to find the function to call (returned in eax) and | 2737 // Call the runtime to find the function to call (returned in eax) and |
(...skipping 23 matching lines...) Expand all Loading... |
2756 // implicitly the global object. | 2761 // implicitly the global object. |
2757 EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT); | 2762 EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT); |
2758 | 2763 |
2759 } else if (property != NULL) { | 2764 } else if (property != NULL) { |
2760 { PreservePositionScope scope(masm()->positions_recorder()); | 2765 { PreservePositionScope scope(masm()->positions_recorder()); |
2761 VisitForStackValue(property->obj()); | 2766 VisitForStackValue(property->obj()); |
2762 } | 2767 } |
2763 if (property->key()->IsPropertyName()) { | 2768 if (property->key()->IsPropertyName()) { |
2764 EmitCallWithIC(expr, | 2769 EmitCallWithIC(expr, |
2765 property->key()->AsLiteral()->value(), | 2770 property->key()->AsLiteral()->value(), |
2766 RelocInfo::CODE_TARGET); | 2771 NOT_CONTEXTUAL); |
2767 } else { | 2772 } else { |
2768 EmitKeyedCallWithIC(expr, property->key()); | 2773 EmitKeyedCallWithIC(expr, property->key()); |
2769 } | 2774 } |
2770 | 2775 |
2771 } else { | 2776 } else { |
2772 // Call to an arbitrary expression not handled specially above. | 2777 // Call to an arbitrary expression not handled specially above. |
2773 { PreservePositionScope scope(masm()->positions_recorder()); | 2778 { PreservePositionScope scope(masm()->positions_recorder()); |
2774 VisitForStackValue(callee); | 2779 VisitForStackValue(callee); |
2775 } | 2780 } |
2776 // Load global receiver object. | 2781 // Load global receiver object. |
(...skipping 1372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4149 | 4154 |
4150 // Push the arguments ("left-to-right"). | 4155 // Push the arguments ("left-to-right"). |
4151 int arg_count = args->length(); | 4156 int arg_count = args->length(); |
4152 for (int i = 0; i < arg_count; i++) { | 4157 for (int i = 0; i < arg_count; i++) { |
4153 VisitForStackValue(args->at(i)); | 4158 VisitForStackValue(args->at(i)); |
4154 } | 4159 } |
4155 | 4160 |
4156 if (expr->is_jsruntime()) { | 4161 if (expr->is_jsruntime()) { |
4157 // Call the JS runtime function via a call IC. | 4162 // Call the JS runtime function via a call IC. |
4158 __ Set(ecx, Immediate(expr->name())); | 4163 __ Set(ecx, Immediate(expr->name())); |
4159 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; | 4164 ContextualMode mode = NOT_CONTEXTUAL; |
4160 Handle<Code> ic = | 4165 Handle<Code> ic = |
4161 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); | 4166 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); |
4162 CallIC(ic, mode, expr->CallRuntimeFeedbackId()); | 4167 CallIC(ic, mode, expr->CallRuntimeFeedbackId()); |
4163 // Restore context register. | 4168 // Restore context register. |
4164 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 4169 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
4165 } else { | 4170 } else { |
4166 // Call the C runtime function. | 4171 // Call the C runtime function. |
4167 __ CallRuntime(expr->function(), arg_count); | 4172 __ CallRuntime(expr->function(), arg_count); |
4168 } | 4173 } |
4169 context()->Plug(eax); | 4174 context()->Plug(eax); |
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4409 | 4414 |
4410 // Record position before stub call. | 4415 // Record position before stub call. |
4411 SetSourcePosition(expr->position()); | 4416 SetSourcePosition(expr->position()); |
4412 | 4417 |
4413 // Call stub for +1/-1. | 4418 // Call stub for +1/-1. |
4414 __ bind(&stub_call); | 4419 __ bind(&stub_call); |
4415 __ mov(edx, eax); | 4420 __ mov(edx, eax); |
4416 __ mov(eax, Immediate(Smi::FromInt(1))); | 4421 __ mov(eax, Immediate(Smi::FromInt(1))); |
4417 BinaryOpStub stub(expr->binary_op(), NO_OVERWRITE); | 4422 BinaryOpStub stub(expr->binary_op(), NO_OVERWRITE); |
4418 CallIC(stub.GetCode(isolate()), | 4423 CallIC(stub.GetCode(isolate()), |
4419 RelocInfo::CODE_TARGET, | 4424 NOT_CONTEXTUAL, |
4420 expr->CountBinOpFeedbackId()); | 4425 expr->CountBinOpFeedbackId()); |
4421 patch_site.EmitPatchInfo(); | 4426 patch_site.EmitPatchInfo(); |
4422 __ bind(&done); | 4427 __ bind(&done); |
4423 | 4428 |
4424 // Store the value returned in eax. | 4429 // Store the value returned in eax. |
4425 switch (assign_type) { | 4430 switch (assign_type) { |
4426 case VARIABLE: | 4431 case VARIABLE: |
4427 if (expr->is_postfix()) { | 4432 if (expr->is_postfix()) { |
4428 // Perform the assignment as if via '='. | 4433 // Perform the assignment as if via '='. |
4429 { EffectContext context(this); | 4434 { EffectContext context(this); |
(...skipping 14 matching lines...) Expand all Loading... |
4444 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4449 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
4445 context()->Plug(eax); | 4450 context()->Plug(eax); |
4446 } | 4451 } |
4447 break; | 4452 break; |
4448 case NAMED_PROPERTY: { | 4453 case NAMED_PROPERTY: { |
4449 __ mov(ecx, prop->key()->AsLiteral()->value()); | 4454 __ mov(ecx, prop->key()->AsLiteral()->value()); |
4450 __ pop(edx); | 4455 __ pop(edx); |
4451 Handle<Code> ic = is_classic_mode() | 4456 Handle<Code> ic = is_classic_mode() |
4452 ? isolate()->builtins()->StoreIC_Initialize() | 4457 ? isolate()->builtins()->StoreIC_Initialize() |
4453 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 4458 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
4454 CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); | 4459 CallIC(ic, NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); |
4455 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4460 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
4456 if (expr->is_postfix()) { | 4461 if (expr->is_postfix()) { |
4457 if (!context()->IsEffect()) { | 4462 if (!context()->IsEffect()) { |
4458 context()->PlugTOS(); | 4463 context()->PlugTOS(); |
4459 } | 4464 } |
4460 } else { | 4465 } else { |
4461 context()->Plug(eax); | 4466 context()->Plug(eax); |
4462 } | 4467 } |
4463 break; | 4468 break; |
4464 } | 4469 } |
4465 case KEYED_PROPERTY: { | 4470 case KEYED_PROPERTY: { |
4466 __ pop(ecx); | 4471 __ pop(ecx); |
4467 __ pop(edx); | 4472 __ pop(edx); |
4468 Handle<Code> ic = is_classic_mode() | 4473 Handle<Code> ic = is_classic_mode() |
4469 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 4474 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
4470 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 4475 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
4471 CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); | 4476 CallIC(ic, NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); |
4472 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4477 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
4473 if (expr->is_postfix()) { | 4478 if (expr->is_postfix()) { |
4474 // Result is on the stack | 4479 // Result is on the stack |
4475 if (!context()->IsEffect()) { | 4480 if (!context()->IsEffect()) { |
4476 context()->PlugTOS(); | 4481 context()->PlugTOS(); |
4477 } | 4482 } |
4478 } else { | 4483 } else { |
4479 context()->Plug(eax); | 4484 context()->Plug(eax); |
4480 } | 4485 } |
4481 break; | 4486 break; |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4651 __ or_(ecx, eax); | 4656 __ or_(ecx, eax); |
4652 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear); | 4657 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear); |
4653 __ cmp(edx, eax); | 4658 __ cmp(edx, eax); |
4654 Split(cc, if_true, if_false, NULL); | 4659 Split(cc, if_true, if_false, NULL); |
4655 __ bind(&slow_case); | 4660 __ bind(&slow_case); |
4656 } | 4661 } |
4657 | 4662 |
4658 // Record position and call the compare IC. | 4663 // Record position and call the compare IC. |
4659 SetSourcePosition(expr->position()); | 4664 SetSourcePosition(expr->position()); |
4660 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 4665 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
4661 CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); | 4666 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); |
4662 patch_site.EmitPatchInfo(); | 4667 patch_site.EmitPatchInfo(); |
4663 | 4668 |
4664 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 4669 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
4665 __ test(eax, eax); | 4670 __ test(eax, eax); |
4666 Split(cc, if_true, if_false, fall_through); | 4671 Split(cc, if_true, if_false, fall_through); |
4667 } | 4672 } |
4668 } | 4673 } |
4669 | 4674 |
4670 // Convert the result of the comparison into one expected for this | 4675 // Convert the result of the comparison into one expected for this |
4671 // expression's context. | 4676 // expression's context. |
(...skipping 15 matching lines...) Expand all Loading... |
4687 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 4692 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
4688 | 4693 |
4689 Handle<Object> nil_value = nil == kNullValue | 4694 Handle<Object> nil_value = nil == kNullValue |
4690 ? isolate()->factory()->null_value() | 4695 ? isolate()->factory()->null_value() |
4691 : isolate()->factory()->undefined_value(); | 4696 : isolate()->factory()->undefined_value(); |
4692 if (expr->op() == Token::EQ_STRICT) { | 4697 if (expr->op() == Token::EQ_STRICT) { |
4693 __ cmp(eax, nil_value); | 4698 __ cmp(eax, nil_value); |
4694 Split(equal, if_true, if_false, fall_through); | 4699 Split(equal, if_true, if_false, fall_through); |
4695 } else { | 4700 } else { |
4696 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); | 4701 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); |
4697 CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); | 4702 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); |
4698 __ test(eax, eax); | 4703 __ test(eax, eax); |
4699 Split(not_zero, if_true, if_false, fall_through); | 4704 Split(not_zero, if_true, if_false, fall_through); |
4700 } | 4705 } |
4701 context()->Plug(if_true, if_false); | 4706 context()->Plug(if_true, if_false); |
4702 } | 4707 } |
4703 | 4708 |
4704 | 4709 |
4705 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 4710 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
4706 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 4711 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
4707 context()->Plug(eax); | 4712 context()->Plug(eax); |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4913 | 4918 |
4914 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), | 4919 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), |
4915 Assembler::target_address_at(call_target_address)); | 4920 Assembler::target_address_at(call_target_address)); |
4916 return OSR_AFTER_STACK_CHECK; | 4921 return OSR_AFTER_STACK_CHECK; |
4917 } | 4922 } |
4918 | 4923 |
4919 | 4924 |
4920 } } // namespace v8::internal | 4925 } } // namespace v8::internal |
4921 | 4926 |
4922 #endif // V8_TARGET_ARCH_IA32 | 4927 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |