Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(600)

Side by Side Diff: src/codegen-ia32.cc

Issue 16536: Experimental: a grab bag of support for register allocation. Push the... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: '' Created 11 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 485 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 } 496 }
497 497
498 498
499 void CodeGenerator::LoadReference(Reference* ref) { 499 void CodeGenerator::LoadReference(Reference* ref) {
500 Comment cmnt(masm_, "[ LoadReference"); 500 Comment cmnt(masm_, "[ LoadReference");
501 Expression* e = ref->expression(); 501 Expression* e = ref->expression();
502 Property* property = e->AsProperty(); 502 Property* property = e->AsProperty();
503 Variable* var = e->AsVariableProxy()->AsVariable(); 503 Variable* var = e->AsVariableProxy()->AsVariable();
504 504
505 if (property != NULL) { 505 if (property != NULL) {
506 VirtualFrame::SpilledScope spilled_scope(this);
507 // The expression is either a property or a variable proxy that rewrites 506 // The expression is either a property or a variable proxy that rewrites
508 // to a property. 507 // to a property.
509 LoadAndSpill(property->obj()); 508 Load(property->obj());
510 // We use a named reference if the key is a literal symbol, unless it is 509 // We use a named reference if the key is a literal symbol, unless it is
511 // a string that can be legally parsed as an integer. This is because 510 // a string that can be legally parsed as an integer. This is because
512 // otherwise we will not get into the slow case code that handles [] on 511 // otherwise we will not get into the slow case code that handles [] on
513 // String objects. 512 // String objects.
514 Literal* literal = property->key()->AsLiteral(); 513 Literal* literal = property->key()->AsLiteral();
515 uint32_t dummy; 514 uint32_t dummy;
516 if (literal != NULL && 515 if (literal != NULL &&
517 literal->handle()->IsSymbol() && 516 literal->handle()->IsSymbol() &&
518 !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) { 517 !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
519 ref->set_type(Reference::NAMED); 518 ref->set_type(Reference::NAMED);
520 } else { 519 } else {
521 LoadAndSpill(property->key()); 520 Load(property->key());
522 ref->set_type(Reference::KEYED); 521 ref->set_type(Reference::KEYED);
523 } 522 }
524 } else if (var != NULL) { 523 } else if (var != NULL) {
525 // The expression is a variable proxy that does not rewrite to a 524 // The expression is a variable proxy that does not rewrite to a
526 // property. Global variables are treated as named property references. 525 // property. Global variables are treated as named property references.
527 if (var->is_global()) { 526 if (var->is_global()) {
528 VirtualFrame::SpilledScope spilled_scope(this); 527 VirtualFrame::SpilledScope spilled_scope(this);
529 LoadGlobal(); 528 LoadGlobal();
530 ref->set_type(Reference::NAMED); 529 ref->set_type(Reference::NAMED);
531 } else { 530 } else {
532 ASSERT(var->slot() != NULL); 531 ASSERT(var->slot() != NULL);
533 ref->set_type(Reference::SLOT); 532 ref->set_type(Reference::SLOT);
534 } 533 }
535 } else { 534 } else {
536 VirtualFrame::SpilledScope spilled_scope(this);
537 // Anything else is a runtime error. 535 // Anything else is a runtime error.
538 LoadAndSpill(e); 536 Load(e);
539 frame_->CallRuntime(Runtime::kThrowReferenceError, 1); 537 frame_->CallRuntime(Runtime::kThrowReferenceError, 1);
540 } 538 }
541 } 539 }
542 540
543 541
544 void CodeGenerator::UnloadReference(Reference* ref) { 542 void CodeGenerator::UnloadReference(Reference* ref) {
545 // Pop a reference from the stack while preserving TOS. 543 // Pop a reference from the stack while preserving TOS.
546 Comment cmnt(masm_, "[ UnloadReference"); 544 Comment cmnt(masm_, "[ UnloadReference");
547 int size = ref->size(); 545 int size = ref->size();
548 if (size == 1) { 546 if (size == 1) {
547 VirtualFrame::SpilledScope spilled_scope(this);
549 frame_->EmitPop(eax); 548 frame_->EmitPop(eax);
550 __ mov(frame_->Top(), eax); 549 __ mov(frame_->Top(), eax);
551 } else if (size > 1) { 550 } else if (size > 1) {
551 VirtualFrame::SpilledScope spilled_scope(this);
552 frame_->EmitPop(eax); 552 frame_->EmitPop(eax);
553 frame_->Drop(size); 553 frame_->Drop(size);
554 frame_->EmitPush(eax); 554 frame_->EmitPush(eax);
555 } 555 }
556 } 556 }
557 557
558 558
559 class ToBooleanStub: public CodeStub { 559 class ToBooleanStub: public CodeStub {
560 public: 560 public:
561 ToBooleanStub() { } 561 ToBooleanStub() { }
(...skipping 1637 matching lines...) Expand 10 before | Expand all | Expand 10 after
2199 2199
2200 // If the property has been removed while iterating, we just skip it. 2200 // If the property has been removed while iterating, we just skip it.
2201 __ cmp(ebx, Factory::null_value()); 2201 __ cmp(ebx, Factory::null_value());
2202 node->continue_target()->Branch(equal); 2202 node->continue_target()->Branch(equal);
2203 2203
2204 end_del_check.Bind(); 2204 end_del_check.Bind();
2205 // Store the entry in the 'each' expression and take another spin in the 2205 // Store the entry in the 'each' expression and take another spin in the
2206 // loop. edx: i'th entry of the enum cache (or string there of) 2206 // loop. edx: i'th entry of the enum cache (or string there of)
2207 frame_->EmitPush(ebx); 2207 frame_->EmitPush(ebx);
2208 { Reference each(this, node->each()); 2208 { Reference each(this, node->each());
2209 // Loading a reference may leave the frame in an unspilled state.
2210 frame_->SpillAll();
2209 if (!each.is_illegal()) { 2211 if (!each.is_illegal()) {
2210 if (each.size() > 0) { 2212 if (each.size() > 0) {
2211 frame_->EmitPush(frame_->ElementAt(each.size())); 2213 frame_->EmitPush(frame_->ElementAt(each.size()));
2212 } 2214 }
2213 // If the reference was to a slot we rely on the convenient property 2215 // If the reference was to a slot we rely on the convenient property
2214 // that it doesn't matter whether a value (eg, ebx pushed above) is 2216 // that it doesn't matter whether a value (eg, ebx pushed above) is
2215 // right on top of or right underneath a zero-sized reference. 2217 // right on top of or right underneath a zero-sized reference.
2216 each.SetValue(NOT_CONST_INIT); 2218 each.SetValue(NOT_CONST_INIT);
2217 if (each.size() > 0) { 2219 if (each.size() > 0) {
2218 // It's safe to pop the value lying on top of the reference before 2220 // It's safe to pop the value lying on top of the reference before
2219 // unloading the reference itself (which preserves the top of stack, 2221 // unloading the reference itself (which preserves the top of stack,
2220 // ie, now the topmost value of the non-zero sized reference), since 2222 // ie, now the topmost value of the non-zero sized reference), since
2221 // we will discard the top of stack after unloading the reference 2223 // we will discard the top of stack after unloading the reference
2222 // anyway. 2224 // anyway.
2223 frame_->Drop(); 2225 frame_->Drop();
2224 } 2226 }
2225 } 2227 }
2226 } 2228 }
2229 // Unloading a reference may leave the frame in an unspilled state.
2230 frame_->SpillAll();
2231
2227 // Discard the i'th entry pushed above or else the remainder of the 2232 // Discard the i'th entry pushed above or else the remainder of the
2228 // reference, whichever is currently on top of the stack. 2233 // reference, whichever is currently on top of the stack.
2229 frame_->Drop(); 2234 frame_->Drop();
2230 2235
2231 // Body. 2236 // Body.
2232 CheckStack(); // TODO(1222600): ignore if body contains calls. 2237 CheckStack(); // TODO(1222600): ignore if body contains calls.
2233 VisitAndSpill(node->body()); 2238 VisitAndSpill(node->body());
2234 2239
2235 // Next. 2240 // Next.
2236 node->continue_target()->Bind(); 2241 node->continue_target()->Bind();
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
2522 frame_->CallRuntime(Runtime::kReThrow, 1); 2527 frame_->CallRuntime(Runtime::kReThrow, 1);
2523 2528
2524 // Done. 2529 // Done.
2525 exit.Bind(); 2530 exit.Bind();
2526 } 2531 }
2527 } 2532 }
2528 2533
2529 2534
2530 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { 2535 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) {
2531 ASSERT(!in_spilled_code()); 2536 ASSERT(!in_spilled_code());
2532 VirtualFrame::SpilledScope spilled_scope(this);
2533 Comment cmnt(masm_, "[ DebuggerStatement"); 2537 Comment cmnt(masm_, "[ DebuggerStatement");
2534 CodeForStatement(node); 2538 CodeForStatement(node);
2539 // Spill everything, even constants, to the frame.
2540 frame_->SpillAll();
2535 frame_->CallRuntime(Runtime::kDebugBreak, 0); 2541 frame_->CallRuntime(Runtime::kDebugBreak, 0);
2536 // Ignore the return value. 2542 // Ignore the return value.
2537 } 2543 }
2538 2544
2539 2545
2540 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) { 2546 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) {
2541 ASSERT(boilerplate->IsBoilerplate()); 2547 ASSERT(boilerplate->IsBoilerplate());
2542 2548
2543 // Push the boilerplate on the stack. 2549 // Push the boilerplate on the stack.
2544 frame_->EmitPush(Immediate(boilerplate)); 2550 frame_->Push(boilerplate);
2545 2551
2546 // Create a new closure. 2552 // Create a new closure.
2547 frame_->EmitPush(esi); 2553 frame_->Push(esi);
2548 frame_->CallRuntime(Runtime::kNewClosure, 2); 2554 Result result = frame_->CallRuntime(Runtime::kNewClosure, 2);
2549 frame_->EmitPush(eax); 2555 frame_->Push(&result);
2550 } 2556 }
2551 2557
2552 2558
2553 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { 2559 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
2554 VirtualFrame::SpilledScope spilled_scope(this);
2555 Comment cmnt(masm_, "[ FunctionLiteral"); 2560 Comment cmnt(masm_, "[ FunctionLiteral");
2556 2561
2557 // Build the function boilerplate and instantiate it. 2562 // Build the function boilerplate and instantiate it.
2558 Handle<JSFunction> boilerplate = BuildBoilerplate(node); 2563 Handle<JSFunction> boilerplate = BuildBoilerplate(node);
2559 // Check for stack-overflow exception. 2564 // Check for stack-overflow exception.
2560 if (HasStackOverflow()) return; 2565 if (HasStackOverflow()) return;
2561 InstantiateBoilerplate(boilerplate); 2566 InstantiateBoilerplate(boilerplate);
2562 } 2567 }
2563 2568
2564 2569
2565 void CodeGenerator::VisitFunctionBoilerplateLiteral( 2570 void CodeGenerator::VisitFunctionBoilerplateLiteral(
2566 FunctionBoilerplateLiteral* node) { 2571 FunctionBoilerplateLiteral* node) {
2567 VirtualFrame::SpilledScope spilled_scope(this);
2568 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral"); 2572 Comment cmnt(masm_, "[ FunctionBoilerplateLiteral");
2569 InstantiateBoilerplate(node->boilerplate()); 2573 InstantiateBoilerplate(node->boilerplate());
2570 } 2574 }
2571 2575
2572 2576
2573 void CodeGenerator::VisitConditional(Conditional* node) { 2577 void CodeGenerator::VisitConditional(Conditional* node) {
2574 VirtualFrame::SpilledScope spilled_scope(this);
2575 Comment cmnt(masm_, "[ Conditional"); 2578 Comment cmnt(masm_, "[ Conditional");
2576 JumpTarget then(this); 2579 JumpTarget then(this);
2577 JumpTarget else_(this); 2580 JumpTarget else_(this);
2578 JumpTarget exit(this); 2581 JumpTarget exit(this);
2579 LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF, 2582 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true);
2580 &then, &else_, true);
2581 if (has_valid_frame()) { 2583 if (has_valid_frame()) {
2582 Branch(false, &else_); 2584 Branch(false, &else_);
2583 } 2585 }
2584 if (has_valid_frame() || then.is_linked()) { 2586 if (then.is_linked()) {
2585 then.Bind(); 2587 then.Bind();
2586 LoadAndSpill(node->then_expression(), typeof_state()); 2588 }
2589 if (has_valid_frame()) {
2590 Load(node->then_expression(), typeof_state());
2587 exit.Jump(); 2591 exit.Jump();
2588 } 2592 }
2589 if (else_.is_linked()) { 2593 if (else_.is_linked()) {
2590 else_.Bind(); 2594 else_.Bind();
2591 LoadAndSpill(node->else_expression(), typeof_state()); 2595 Load(node->else_expression(), typeof_state());
2592 } 2596 }
2593 exit.Bind(); 2597 exit.Bind();
2594 } 2598 }
2595 2599
2596 2600
2597 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { 2601 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
2598 if (slot->type() == Slot::LOOKUP) { 2602 if (slot->type() == Slot::LOOKUP) {
2599 ASSERT(slot->var()->mode() == Variable::DYNAMIC); 2603 ASSERT(slot->var()->mode() == Variable::DYNAMIC);
2600 2604
2601 // For now, just do a runtime call. 2605 // For now, just do a runtime call.
2602 VirtualFrame::SpilledScope spilled_scope(this); 2606 frame_->Push(esi);
2603 frame_->EmitPush(esi); 2607 frame_->Push(slot->var()->name());
2604 frame_->EmitPush(Immediate(slot->var()->name()));
2605 2608
2609 Result value(this);
2606 if (typeof_state == INSIDE_TYPEOF) { 2610 if (typeof_state == INSIDE_TYPEOF) {
2607 frame_->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 2611 value =
2612 frame_->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
2608 } else { 2613 } else {
2609 frame_->CallRuntime(Runtime::kLoadContextSlot, 2); 2614 value = frame_->CallRuntime(Runtime::kLoadContextSlot, 2);
2610 } 2615 }
2611 frame_->EmitPush(eax); 2616 frame_->Push(&value);
2617
2618 } else if (slot->var()->mode() == Variable::CONST) {
2619 // Const slots may contain 'the hole' value (the constant hasn't been
2620 // initialized yet) which needs to be converted into the 'undefined'
2621 // value.
2622 Comment cmnt(masm_, "[ Load const");
2623 JumpTarget exit(this);
2624 Result temp = allocator_->Allocate();
2625 ASSERT(temp.is_valid());
2626 __ mov(temp.reg(), SlotOperand(slot, temp.reg()));
William Hesse 2009/01/06 14:40:27 This was __mov(eax, SlotOperand(slot, ecx)). What
2627 __ cmp(temp.reg(), Factory::the_hole_value());
2628 exit.Branch(not_equal, &temp);
2629 __ mov(temp.reg(), Factory::undefined_value());
2630 exit.Bind(&temp);
2631 frame_->Push(&temp);
2632
2633 } else if (slot->type() == Slot::PARAMETER) {
2634 frame_->LoadParameterAt(slot->index());
2635
2636 } else if (slot->type() == Slot::LOCAL) {
2637 frame_->LoadLocalAt(slot->index());
2612 2638
2613 } else { 2639 } else {
2614 // Note: We would like to keep the assert below, but it fires because of 2640 // The other remaining slot types (LOOKUP and GLOBAL) cannot reach
2615 // some nasty code in LoadTypeofExpression() which should be removed... 2641 // here.
2616 // ASSERT(slot->var()->mode() != Variable::DYNAMIC); 2642 ASSERT(slot->type() == Slot::CONTEXT);
2617 if (slot->var()->mode() == Variable::CONST) { 2643 Result temp = allocator_->Allocate();
2618 // Const slots may contain 'the hole' value (the constant hasn't been 2644 ASSERT(temp.is_valid());
2619 // initialized yet) which needs to be converted into the 'undefined' 2645 __ mov(temp.reg(), SlotOperand(slot, temp.reg()));
William Hesse 2009/01/06 14:40:27 Same here, second arg of SlotOperand() was ecx.
2620 // value. 2646 frame_->Push(&temp);
2621 VirtualFrame::SpilledScope spilled_scope(this);
2622 Comment cmnt(masm_, "[ Load const");
2623 JumpTarget exit(this);
2624 __ mov(eax, SlotOperand(slot, ecx));
2625 __ cmp(eax, Factory::the_hole_value());
2626 exit.Branch(not_equal);
2627 __ mov(eax, Factory::undefined_value());
2628 exit.Bind();
2629 frame_->EmitPush(eax);
2630 } else {
2631 if (slot->type() == Slot::PARAMETER) {
2632 frame_->LoadParameterAt(slot->index());
2633 } else if (slot->type() == Slot::LOCAL) {
2634 frame_->LoadLocalAt(slot->index());
2635 } else {
2636 // The other remaining slot types (LOOKUP and GLOBAL) cannot reach
2637 // here.
2638 ASSERT(slot->type() == Slot::CONTEXT);
2639 VirtualFrame::SpilledScope spilled_scope(this);
2640 frame_->EmitPush(SlotOperand(slot, ecx));
2641 }
2642 }
2643 } 2647 }
2644 } 2648 }
2645 2649
2646 2650
2647 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) { 2651 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) {
2648 if (slot->type() == Slot::LOOKUP) { 2652 if (slot->type() == Slot::LOOKUP) {
2649 ASSERT(slot->var()->mode() == Variable::DYNAMIC); 2653 ASSERT(slot->var()->mode() == Variable::DYNAMIC);
2650 2654
2651 // For now, just do a runtime call. 2655 // For now, just do a runtime call.
2652 VirtualFrame::SpilledScope spilled_scope(this); 2656 frame_->Push(esi);
2653 frame_->EmitPush(esi); 2657 frame_->Push(slot->var()->name());
2654 frame_->EmitPush(Immediate(slot->var()->name()));
2655 2658
2659 Result value(this);
2656 if (init_state == CONST_INIT) { 2660 if (init_state == CONST_INIT) {
2657 // Same as the case for a normal store, but ignores attribute 2661 // Same as the case for a normal store, but ignores attribute
2658 // (e.g. READ_ONLY) of context slot so that we can initialize const 2662 // (e.g. READ_ONLY) of context slot so that we can initialize const
2659 // properties (introduced via eval("const foo = (some expr);")). Also, 2663 // properties (introduced via eval("const foo = (some expr);")). Also,
2660 // uses the current function context instead of the top context. 2664 // uses the current function context instead of the top context.
2661 // 2665 //
2662 // Note that we must declare the foo upon entry of eval(), via a 2666 // Note that we must declare the foo upon entry of eval(), via a
2663 // context slot declaration, but we cannot initialize it at the same 2667 // context slot declaration, but we cannot initialize it at the same
2664 // time, because the const declaration may be at the end of the eval 2668 // time, because the const declaration may be at the end of the eval
2665 // code (sigh...) and the const variable may have been used before 2669 // code (sigh...) and the const variable may have been used before
2666 // (where its value is 'undefined'). Thus, we can only do the 2670 // (where its value is 'undefined'). Thus, we can only do the
2667 // initialization when we actually encounter the expression and when 2671 // initialization when we actually encounter the expression and when
2668 // the expression operands are defined and valid, and thus we need the 2672 // the expression operands are defined and valid, and thus we need the
2669 // split into 2 operations: declaration of the context slot followed 2673 // split into 2 operations: declaration of the context slot followed
2670 // by initialization. 2674 // by initialization.
2671 frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3); 2675 value = frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3);
2672 } else { 2676 } else {
2673 frame_->CallRuntime(Runtime::kStoreContextSlot, 3); 2677 value = frame_->CallRuntime(Runtime::kStoreContextSlot, 3);
2674 } 2678 }
2675 // Storing a variable must keep the (new) value on the expression 2679 // Storing a variable must keep the (new) value on the expression
2676 // stack. This is necessary for compiling chained assignment 2680 // stack. This is necessary for compiling chained assignment
2677 // expressions. 2681 // expressions.
2678 frame_->EmitPush(eax); 2682 frame_->Push(&value);
2679 2683
2680 } else { 2684 } else {
2681 ASSERT(slot->var()->mode() != Variable::DYNAMIC); 2685 ASSERT(slot->var()->mode() != Variable::DYNAMIC);
2682 2686
2683 JumpTarget exit(this); 2687 JumpTarget exit(this);
2684 if (init_state == CONST_INIT) { 2688 if (init_state == CONST_INIT) {
2685 ASSERT(slot->var()->mode() == Variable::CONST); 2689 ASSERT(slot->var()->mode() == Variable::CONST);
2686 // Only the first const initialization must be executed (the slot 2690 // Only the first const initialization must be executed (the slot
2687 // still contains 'the hole' value). When the assignment is executed, 2691 // still contains 'the hole' value). When the assignment is executed,
2688 // the code is identical to a normal store (see below). 2692 // the code is identical to a normal store (see below).
2689 Comment cmnt(masm_, "[ Init const"); 2693 Comment cmnt(masm_, "[ Init const");
2690 VirtualFrame::SpilledScope spilled_scope(this); 2694 Result temp = allocator_->Allocate();
2691 __ mov(eax, SlotOperand(slot, ecx)); 2695 ASSERT(temp.is_valid());
2692 __ cmp(eax, Factory::the_hole_value()); 2696 __ mov(temp.reg(), SlotOperand(slot, temp.reg()));
William Hesse 2009/01/06 14:40:27 Same, ecx versus eax.
2697 __ cmp(temp.reg(), Factory::the_hole_value());
2698 temp.Unuse();
2693 exit.Branch(not_equal); 2699 exit.Branch(not_equal);
2694 } 2700 }
2695 2701
2696 // We must execute the store. Storing a variable must keep the (new) 2702 // We must execute the store. Storing a variable must keep the (new)
2697 // value on the stack. This is necessary for compiling assignment 2703 // value on the stack. This is necessary for compiling assignment
2698 // expressions. 2704 // expressions.
2699 // 2705 //
2700 // Note: We will reach here even with slot->var()->mode() == 2706 // Note: We will reach here even with slot->var()->mode() ==
2701 // Variable::CONST because of const declarations which will initialize 2707 // Variable::CONST because of const declarations which will initialize
2702 // consts to 'the hole' value and by doing so, end up calling this code. 2708 // consts to 'the hole' value and by doing so, end up calling this code.
2703 if (slot->type() == Slot::PARAMETER) { 2709 if (slot->type() == Slot::PARAMETER) {
2704 frame_->StoreToParameterAt(slot->index()); 2710 frame_->StoreToParameterAt(slot->index());
2705 } else if (slot->type() == Slot::LOCAL) { 2711 } else if (slot->type() == Slot::LOCAL) {
2706 frame_->StoreToLocalAt(slot->index()); 2712 frame_->StoreToLocalAt(slot->index());
2707 } else { 2713 } else {
2708 // The other slot types (LOOKUP and GLOBAL) cannot reach here. 2714 // The other slot types (LOOKUP and GLOBAL) cannot reach here.
2709 ASSERT(slot->type() == Slot::CONTEXT); 2715 ASSERT(slot->type() == Slot::CONTEXT);
2710 VirtualFrame::SpilledScope spilled_scope(this); 2716 frame_->Dup();
2711 frame_->EmitPop(eax); 2717 Result value = frame_->Pop();
2712 __ mov(SlotOperand(slot, ecx), eax); 2718 value.ToRegister();
2713 frame_->EmitPush(eax); // RecordWrite may destroy the value in eax. 2719 Result start = allocator_->Allocate();
2720 ASSERT(start.is_valid());
2721 __ mov(SlotOperand(slot, start.reg()), value.reg());
2722 // RecordWrite may destroy the value registers.
2723 //
2724 // TODO(): Avoid actually spilling when the value is not needed
2725 // (probably the common case).
2726 frame_->Spill(value.reg());
2714 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 2727 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
2715 __ RecordWrite(ecx, offset, eax, ebx); 2728 Result temp = allocator_->Allocate();
2729 ASSERT(temp.is_valid());
2730 __ RecordWrite(start.reg(), offset, value.reg(), temp.reg());
2731 // The results start, value, and temp are unused by going out of
2732 // scope.
2716 } 2733 }
2717 2734
2718 // If we definitely did not jump over the assignment, we do not need 2735 // If we definitely did not jump over the assignment, we do not need
2719 // to bind the exit label. Doing so can defeat peephole 2736 // to bind the exit label. Doing so can defeat peephole
2720 // optimization. 2737 // optimization.
2721 if (init_state == CONST_INIT) { 2738 if (exit.is_linked()) {
2722 exit.Bind(); 2739 exit.Bind();
2723 } 2740 }
2724 } 2741 }
2725 } 2742 }
2726 2743
2727 2744
2728 void CodeGenerator::VisitSlot(Slot* node) { 2745 void CodeGenerator::VisitSlot(Slot* node) {
2729 Comment cmnt(masm_, "[ Slot"); 2746 Comment cmnt(masm_, "[ Slot");
2730 LoadFromSlot(node, typeof_state()); 2747 LoadFromSlot(node, typeof_state());
2731 } 2748 }
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
3017 3034
3018 3035
3019 void CodeGenerator::VisitAssignment(Assignment* node) { 3036 void CodeGenerator::VisitAssignment(Assignment* node) {
3020 Comment cmnt(masm_, "[ Assignment"); 3037 Comment cmnt(masm_, "[ Assignment");
3021 CodeForStatement(node); 3038 CodeForStatement(node);
3022 3039
3023 { Reference target(this, node->target()); 3040 { Reference target(this, node->target());
3024 if (target.is_illegal()) { 3041 if (target.is_illegal()) {
3025 // Fool the virtual frame into thinking that we left the assignment's 3042 // Fool the virtual frame into thinking that we left the assignment's
3026 // value on the frame. 3043 // value on the frame.
3027 frame_->EmitPush(Immediate(Smi::FromInt(0))); 3044 frame_->Push(Handle<Object>(Smi::FromInt(0)));
3028 return; 3045 return;
3029 } 3046 }
3030 3047
3031 if (node->op() == Token::ASSIGN || 3048 if (node->op() == Token::ASSIGN ||
3032 node->op() == Token::INIT_VAR || 3049 node->op() == Token::INIT_VAR ||
3033 node->op() == Token::INIT_CONST) { 3050 node->op() == Token::INIT_CONST) {
3034 Load(node->value()); 3051 Load(node->value());
3035 3052
3036 } else { 3053 } else {
3037 VirtualFrame::SpilledScope spilled_scope(this); 3054 VirtualFrame::SpilledScope spilled_scope(this);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
3071 Comment cmnt(masm_, "[ Throw"); 3088 Comment cmnt(masm_, "[ Throw");
3072 CodeForStatement(node); 3089 CodeForStatement(node);
3073 3090
3074 LoadAndSpill(node->exception()); 3091 LoadAndSpill(node->exception());
3075 frame_->CallRuntime(Runtime::kThrow, 1); 3092 frame_->CallRuntime(Runtime::kThrow, 1);
3076 frame_->EmitPush(eax); 3093 frame_->EmitPush(eax);
3077 } 3094 }
3078 3095
3079 3096
3080 void CodeGenerator::VisitProperty(Property* node) { 3097 void CodeGenerator::VisitProperty(Property* node) {
3081 VirtualFrame::SpilledScope spilled_scope(this);
3082 Comment cmnt(masm_, "[ Property"); 3098 Comment cmnt(masm_, "[ Property");
3083 Reference property(this, node); 3099 Reference property(this, node);
3084 property.GetValueAndSpill(typeof_state()); 3100 property.GetValue(typeof_state());
3085 } 3101 }
3086 3102
3087 3103
3088 void CodeGenerator::VisitCall(Call* node) { 3104 void CodeGenerator::VisitCall(Call* node) {
3089 VirtualFrame::SpilledScope spilled_scope(this); 3105 VirtualFrame::SpilledScope spilled_scope(this);
3090 Comment cmnt(masm_, "[ Call"); 3106 Comment cmnt(masm_, "[ Call");
3091 3107
3092 ZoneList<Expression*>* args = node->arguments(); 3108 ZoneList<Expression*>* args = node->arguments();
3093 3109
3094 CodeForStatement(node); 3110 CodeForStatement(node);
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
3186 // Overwrite the function on the stack with the result. 3202 // Overwrite the function on the stack with the result.
3187 __ mov(frame_->Top(), eax); 3203 __ mov(frame_->Top(), eax);
3188 3204
3189 } else { 3205 } else {
3190 // ------------------------------------------- 3206 // -------------------------------------------
3191 // JavaScript example: 'array[index](1, 2, 3)' 3207 // JavaScript example: 'array[index](1, 2, 3)'
3192 // ------------------------------------------- 3208 // -------------------------------------------
3193 3209
3194 // Load the function to call from the property through a reference. 3210 // Load the function to call from the property through a reference.
3195 Reference ref(this, property); 3211 Reference ref(this, property);
3212 frame_->SpillAll();
3196 ref.GetValueAndSpill(NOT_INSIDE_TYPEOF); 3213 ref.GetValueAndSpill(NOT_INSIDE_TYPEOF);
3197 3214
3198 // Pass receiver to called function. 3215 // Pass receiver to called function.
3199 // The reference's size is non-negative. 3216 // The reference's size is non-negative.
3200 frame_->EmitPush(frame_->ElementAt(ref.size())); 3217 frame_->EmitPush(frame_->ElementAt(ref.size()));
3201 3218
3202 // Call the function. 3219 // Call the function.
3203 CallWithArguments(args, node->position()); 3220 CallWithArguments(args, node->position());
3204 } 3221 }
3205 3222
(...skipping 2601 matching lines...) Expand 10 before | Expand all | Expand 10 after
5807 5824
5808 // Slow-case: Go through the JavaScript implementation. 5825 // Slow-case: Go through the JavaScript implementation.
5809 __ bind(&slow); 5826 __ bind(&slow);
5810 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 5827 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
5811 } 5828 }
5812 5829
5813 5830
5814 #undef __ 5831 #undef __
5815 5832
5816 } } // namespace v8::internal 5833 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698