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

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

Issue 113837: Change the register allocator so that it no longer tracks references... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 7 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
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 372 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 return Operand(eax); 383 return Operand(eax);
384 } 384 }
385 } 385 }
386 386
387 387
388 Operand CodeGenerator::ContextSlotOperandCheckExtensions(Slot* slot, 388 Operand CodeGenerator::ContextSlotOperandCheckExtensions(Slot* slot,
389 Result tmp, 389 Result tmp,
390 JumpTarget* slow) { 390 JumpTarget* slow) {
391 ASSERT(slot->type() == Slot::CONTEXT); 391 ASSERT(slot->type() == Slot::CONTEXT);
392 ASSERT(tmp.is_register()); 392 ASSERT(tmp.is_register());
393 Result context(esi); 393 Register context = esi;
394 394
395 for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) { 395 for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) {
396 if (s->num_heap_slots() > 0) { 396 if (s->num_heap_slots() > 0) {
397 if (s->calls_eval()) { 397 if (s->calls_eval()) {
398 // Check that extension is NULL. 398 // Check that extension is NULL.
399 __ cmp(ContextOperand(context.reg(), Context::EXTENSION_INDEX), 399 __ cmp(ContextOperand(context, Context::EXTENSION_INDEX),
400 Immediate(0)); 400 Immediate(0));
401 slow->Branch(not_equal, not_taken); 401 slow->Branch(not_equal, not_taken);
402 } 402 }
403 __ mov(tmp.reg(), ContextOperand(context.reg(), Context::CLOSURE_INDEX)); 403 __ mov(tmp.reg(), ContextOperand(context, Context::CLOSURE_INDEX));
404 __ mov(tmp.reg(), FieldOperand(tmp.reg(), JSFunction::kContextOffset)); 404 __ mov(tmp.reg(), FieldOperand(tmp.reg(), JSFunction::kContextOffset));
405 context = tmp; 405 context = tmp.reg();
406 } 406 }
407 } 407 }
408 // Check that last extension is NULL. 408 // Check that last extension is NULL.
409 __ cmp(ContextOperand(context.reg(), Context::EXTENSION_INDEX), 409 __ cmp(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0));
410 Immediate(0));
411 slow->Branch(not_equal, not_taken); 410 slow->Branch(not_equal, not_taken);
412 __ mov(tmp.reg(), ContextOperand(context.reg(), Context::FCONTEXT_INDEX)); 411 __ mov(tmp.reg(), ContextOperand(context, Context::FCONTEXT_INDEX));
413 return ContextOperand(tmp.reg(), slot->index()); 412 return ContextOperand(tmp.reg(), slot->index());
414 } 413 }
415 414
416 415
417 // Emit code to load the value of an expression to the top of the 416 // Emit code to load the value of an expression to the top of the
418 // frame. If the expression is boolean-valued it may be compiled (or 417 // frame. If the expression is boolean-valued it may be compiled (or
419 // partially compiled) into control flow to the control destination. 418 // partially compiled) into control flow to the control destination.
420 // If force_control is true, control flow is forced. 419 // If force_control is true, control flow is forced.
421 void CodeGenerator::LoadCondition(Expression* x, 420 void CodeGenerator::LoadCondition(Expression* x,
422 TypeofState typeof_state, 421 TypeofState typeof_state,
(...skipping 1342 matching lines...) Expand 10 before | Expand all | Expand 10 after
1765 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); 1764 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
1766 VisitStatements(node->statements()); 1765 VisitStatements(node->statements());
1767 if (node->break_target()->is_linked()) { 1766 if (node->break_target()->is_linked()) {
1768 node->break_target()->Bind(); 1767 node->break_target()->Bind();
1769 } 1768 }
1770 node->break_target()->Unuse(); 1769 node->break_target()->Unuse();
1771 } 1770 }
1772 1771
1773 1772
1774 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 1773 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
1775 frame_->Push(pairs); 1774 // Call the runtime to declare the globals. The inevitable call
1775 // will sync frame elements to memory anyway, so we do it eagerly to
1776 // allow us to push the arguments directly into place.
1777 frame_->SyncRange(0, frame_->element_count() - 1);
1776 1778
1777 // Duplicate the context register. 1779 frame_->EmitPush(Immediate(pairs));
1778 Result context(esi); 1780 frame_->EmitPush(esi); // The context is the second argument.
1779 frame_->Push(&context); 1781 frame_->EmitPush(Immediate(Smi::FromInt(is_eval() ? 1 : 0)));
1780
1781 frame_->Push(Smi::FromInt(is_eval() ? 1 : 0));
1782 Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 3); 1782 Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 3);
1783 // Return value is ignored. 1783 // Return value is ignored.
1784 } 1784 }
1785 1785
1786 1786
1787 void CodeGenerator::VisitDeclaration(Declaration* node) { 1787 void CodeGenerator::VisitDeclaration(Declaration* node) {
1788 Comment cmnt(masm_, "[ Declaration"); 1788 Comment cmnt(masm_, "[ Declaration");
1789 CodeForStatementPosition(node); 1789 CodeForStatementPosition(node);
1790 Variable* var = node->proxy()->var(); 1790 Variable* var = node->proxy()->var();
1791 ASSERT(var != NULL); // must have been resolved 1791 ASSERT(var != NULL); // must have been resolved
1792 Slot* slot = var->slot(); 1792 Slot* slot = var->slot();
1793 1793
1794 // If it was not possible to allocate the variable at compile time, 1794 // If it was not possible to allocate the variable at compile time,
1795 // we need to "declare" it at runtime to make sure it actually 1795 // we need to "declare" it at runtime to make sure it actually
1796 // exists in the local context. 1796 // exists in the local context.
1797 if (slot != NULL && slot->type() == Slot::LOOKUP) { 1797 if (slot != NULL && slot->type() == Slot::LOOKUP) {
1798 // Variables with a "LOOKUP" slot were introduced as non-locals 1798 // Variables with a "LOOKUP" slot were introduced as non-locals
1799 // during variable resolution and must have mode DYNAMIC. 1799 // during variable resolution and must have mode DYNAMIC.
1800 ASSERT(var->is_dynamic()); 1800 ASSERT(var->is_dynamic());
1801 // For now, just do a runtime call. Duplicate the context register. 1801 // For now, just do a runtime call. Sync the virtual frame eagerly
1802 Result context(esi); 1802 // so we can simply push the arguments into place.
1803 frame_->Push(&context); 1803 frame_->SyncRange(0, frame_->element_count() - 1);
1804 frame_->Push(var->name()); 1804 frame_->EmitPush(esi);
1805 frame_->EmitPush(Immediate(var->name()));
1805 // Declaration nodes are always introduced in one of two modes. 1806 // Declaration nodes are always introduced in one of two modes.
1806 ASSERT(node->mode() == Variable::VAR || node->mode() == Variable::CONST); 1807 ASSERT(node->mode() == Variable::VAR || node->mode() == Variable::CONST);
1807 PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY; 1808 PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY;
1808 frame_->Push(Smi::FromInt(attr)); 1809 frame_->EmitPush(Immediate(Smi::FromInt(attr)));
1809 // Push initial value, if any. 1810 // Push initial value, if any.
1810 // Note: For variables we must not push an initial value (such as 1811 // Note: For variables we must not push an initial value (such as
1811 // 'undefined') because we may have a (legal) redeclaration and we 1812 // 'undefined') because we may have a (legal) redeclaration and we
1812 // must not destroy the current value. 1813 // must not destroy the current value.
1813 if (node->mode() == Variable::CONST) { 1814 if (node->mode() == Variable::CONST) {
1814 frame_->Push(Factory::the_hole_value()); 1815 frame_->EmitPush(Immediate(Factory::the_hole_value()));
1815 } else if (node->fun() != NULL) { 1816 } else if (node->fun() != NULL) {
1816 Load(node->fun()); 1817 Load(node->fun());
1817 } else { 1818 } else {
1818 frame_->Push(Smi::FromInt(0)); // no initial value! 1819 frame_->EmitPush(Immediate(Smi::FromInt(0))); // no initial value!
1819 } 1820 }
1820 Result ignored = frame_->CallRuntime(Runtime::kDeclareContextSlot, 4); 1821 Result ignored = frame_->CallRuntime(Runtime::kDeclareContextSlot, 4);
1821 // Ignore the return value (declarations are statements). 1822 // Ignore the return value (declarations are statements).
1822 return; 1823 return;
1823 } 1824 }
1824 1825
1825 ASSERT(!var->is_global()); 1826 ASSERT(!var->is_global());
1826 1827
1827 // If we have a function or a constant, we need to initialize the variable. 1828 // If we have a function or a constant, we need to initialize the variable.
1828 Expression* val = NULL; 1829 Expression* val = NULL;
(...skipping 1353 matching lines...) Expand 10 before | Expand all | Expand 10 after
3182 #ifdef ENABLE_DEBUGGER_SUPPORT 3183 #ifdef ENABLE_DEBUGGER_SUPPORT
3183 // Spill everything, even constants, to the frame. 3184 // Spill everything, even constants, to the frame.
3184 frame_->SpillAll(); 3185 frame_->SpillAll();
3185 frame_->CallRuntime(Runtime::kDebugBreak, 0); 3186 frame_->CallRuntime(Runtime::kDebugBreak, 0);
3186 // Ignore the return value. 3187 // Ignore the return value.
3187 #endif 3188 #endif
3188 } 3189 }
3189 3190
3190 3191
3191 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) { 3192 void CodeGenerator::InstantiateBoilerplate(Handle<JSFunction> boilerplate) {
3193 // Call the runtime to instantiate the function boilerplate object.
3194 // The inevitable call will sync frame elements to memory anyway, so
3195 // we do it eagerly to allow us to push the arguments directly into
3196 // place.
3192 ASSERT(boilerplate->IsBoilerplate()); 3197 ASSERT(boilerplate->IsBoilerplate());
3198 frame_->SyncRange(0, frame_->element_count() - 1);
3193 3199
3194 // Push the boilerplate on the stack. 3200 // Push the boilerplate on the stack.
3195 frame_->Push(boilerplate); 3201 frame_->EmitPush(Immediate(boilerplate));
3196 3202
3197 // Create a new closure. 3203 // Create a new closure.
3198 frame_->Push(esi); 3204 frame_->EmitPush(esi);
3199 Result result = frame_->CallRuntime(Runtime::kNewClosure, 2); 3205 Result result = frame_->CallRuntime(Runtime::kNewClosure, 2);
3200 frame_->Push(&result); 3206 frame_->Push(&result);
3201 } 3207 }
3202 3208
3203 3209
3204 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { 3210 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
3205 Comment cmnt(masm_, "[ FunctionLiteral"); 3211 Comment cmnt(masm_, "[ FunctionLiteral");
3206 3212
3207 // Build the function boilerplate and instantiate it. 3213 // Build the function boilerplate and instantiate it.
3208 Handle<JSFunction> boilerplate = BuildBoilerplate(node); 3214 Handle<JSFunction> boilerplate = BuildBoilerplate(node);
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
3294 __ mov(value.reg(), Factory::undefined_value()); 3300 __ mov(value.reg(), Factory::undefined_value());
3295 } 3301 }
3296 // There is always control flow to slow from 3302 // There is always control flow to slow from
3297 // ContextSlotOperandCheckExtensions so we have to jump around 3303 // ContextSlotOperandCheckExtensions so we have to jump around
3298 // it. 3304 // it.
3299 done.Jump(&value); 3305 done.Jump(&value);
3300 } 3306 }
3301 } 3307 }
3302 3308
3303 slow.Bind(); 3309 slow.Bind();
3304 frame_->Push(esi); 3310 // A runtime call is inevitable. We eagerly sync frame elements
3305 frame_->Push(slot->var()->name()); 3311 // to memory so that we can push the arguments directly into place
3312 // on top of the frame.
3313 frame_->SyncRange(0, frame_->element_count() - 1);
3314 frame_->EmitPush(esi);
3315 frame_->EmitPush(Immediate(slot->var()->name()));
3306 if (typeof_state == INSIDE_TYPEOF) { 3316 if (typeof_state == INSIDE_TYPEOF) {
3307 value = 3317 value =
3308 frame_->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 3318 frame_->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
3309 } else { 3319 } else {
3310 value = frame_->CallRuntime(Runtime::kLoadContextSlot, 2); 3320 value = frame_->CallRuntime(Runtime::kLoadContextSlot, 2);
3311 } 3321 }
3312 3322
3313 done.Bind(&value); 3323 done.Bind(&value);
3314 frame_->Push(&value); 3324 frame_->Push(&value);
3315 3325
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
3350 } 3360 }
3351 } 3361 }
3352 3362
3353 3363
3354 Result CodeGenerator::LoadFromGlobalSlotCheckExtensions( 3364 Result CodeGenerator::LoadFromGlobalSlotCheckExtensions(
3355 Slot* slot, 3365 Slot* slot,
3356 TypeofState typeof_state, 3366 TypeofState typeof_state,
3357 JumpTarget* slow) { 3367 JumpTarget* slow) {
3358 // Check that no extension objects have been created by calls to 3368 // Check that no extension objects have been created by calls to
3359 // eval from the current scope to the global scope. 3369 // eval from the current scope to the global scope.
3360 Result context(esi); 3370 Register context = esi;
3361 Result tmp = allocator_->Allocate(); 3371 Result tmp = allocator_->Allocate();
3362 ASSERT(tmp.is_valid()); // All non-reserved registers were available. 3372 ASSERT(tmp.is_valid()); // All non-reserved registers were available.
3363 3373
3364 Scope* s = scope(); 3374 Scope* s = scope();
3365 while (s != NULL) { 3375 while (s != NULL) {
3366 if (s->num_heap_slots() > 0) { 3376 if (s->num_heap_slots() > 0) {
3367 if (s->calls_eval()) { 3377 if (s->calls_eval()) {
3368 // Check that extension is NULL. 3378 // Check that extension is NULL.
3369 __ cmp(ContextOperand(context.reg(), Context::EXTENSION_INDEX), 3379 __ cmp(ContextOperand(context, Context::EXTENSION_INDEX),
3370 Immediate(0)); 3380 Immediate(0));
3371 slow->Branch(not_equal, not_taken); 3381 slow->Branch(not_equal, not_taken);
3372 } 3382 }
3373 // Load next context in chain. 3383 // Load next context in chain.
3374 __ mov(tmp.reg(), ContextOperand(context.reg(), Context::CLOSURE_INDEX)); 3384 __ mov(tmp.reg(), ContextOperand(context, Context::CLOSURE_INDEX));
3375 __ mov(tmp.reg(), FieldOperand(tmp.reg(), JSFunction::kContextOffset)); 3385 __ mov(tmp.reg(), FieldOperand(tmp.reg(), JSFunction::kContextOffset));
3376 context = tmp; 3386 context = tmp.reg();
3377 } 3387 }
3378 // If no outer scope calls eval, we do not need to check more 3388 // If no outer scope calls eval, we do not need to check more
3379 // context extensions. If we have reached an eval scope, we check 3389 // context extensions. If we have reached an eval scope, we check
3380 // all extensions from this point. 3390 // all extensions from this point.
3381 if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break; 3391 if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break;
3382 s = s->outer_scope(); 3392 s = s->outer_scope();
3383 } 3393 }
3384 3394
3385 if (s->is_eval_scope()) { 3395 if (s->is_eval_scope()) {
3386 // Loop up the context chain. There is no frame effect so it is 3396 // Loop up the context chain. There is no frame effect so it is
3387 // safe to use raw labels here. 3397 // safe to use raw labels here.
3388 Label next, fast; 3398 Label next, fast;
3389 if (!context.reg().is(tmp.reg())) { 3399 if (!context.is(tmp.reg())) {
3390 __ mov(tmp.reg(), context.reg()); 3400 __ mov(tmp.reg(), context);
3391 } 3401 }
3392 __ bind(&next); 3402 __ bind(&next);
3393 // Terminate at global context. 3403 // Terminate at global context.
3394 __ cmp(FieldOperand(tmp.reg(), HeapObject::kMapOffset), 3404 __ cmp(FieldOperand(tmp.reg(), HeapObject::kMapOffset),
3395 Immediate(Factory::global_context_map())); 3405 Immediate(Factory::global_context_map()));
3396 __ j(equal, &fast); 3406 __ j(equal, &fast);
3397 // Check that extension is NULL. 3407 // Check that extension is NULL.
3398 __ cmp(ContextOperand(tmp.reg(), Context::EXTENSION_INDEX), Immediate(0)); 3408 __ cmp(ContextOperand(tmp.reg(), Context::EXTENSION_INDEX), Immediate(0));
3399 slow->Branch(not_equal, not_taken); 3409 slow->Branch(not_equal, not_taken);
3400 // Load next context in chain. 3410 // Load next context in chain.
3401 __ mov(tmp.reg(), ContextOperand(tmp.reg(), Context::CLOSURE_INDEX)); 3411 __ mov(tmp.reg(), ContextOperand(tmp.reg(), Context::CLOSURE_INDEX));
3402 __ mov(tmp.reg(), FieldOperand(tmp.reg(), JSFunction::kContextOffset)); 3412 __ mov(tmp.reg(), FieldOperand(tmp.reg(), JSFunction::kContextOffset));
3403 __ jmp(&next); 3413 __ jmp(&next);
3404 __ bind(&fast); 3414 __ bind(&fast);
3405 } 3415 }
3406 context.Unuse();
3407 tmp.Unuse(); 3416 tmp.Unuse();
3408 3417
3409 // All extension objects were empty and it is safe to use a global 3418 // All extension objects were empty and it is safe to use a global
3410 // load IC call. 3419 // load IC call.
3411 LoadGlobal(); 3420 LoadGlobal();
3412 frame_->Push(slot->var()->name()); 3421 frame_->Push(slot->var()->name());
3413 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) 3422 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
3414 ? RelocInfo::CODE_TARGET 3423 ? RelocInfo::CODE_TARGET
3415 : RelocInfo::CODE_TARGET_CONTEXT; 3424 : RelocInfo::CODE_TARGET_CONTEXT;
3416 Result answer = frame_->CallLoadIC(mode); 3425 Result answer = frame_->CallLoadIC(mode);
3417 // A test eax instruction following the call signals that the inobject 3426 // A test eax instruction following the call signals that the inobject
3418 // property case was inlined. Ensure that there is not a test eax 3427 // property case was inlined. Ensure that there is not a test eax
3419 // instruction here. 3428 // instruction here.
3420 __ nop(); 3429 __ nop();
3421 // Discard the global object. The result is in answer. 3430 // Discard the global object. The result is in answer.
3422 frame_->Drop(); 3431 frame_->Drop();
3423 return answer; 3432 return answer;
3424 } 3433 }
3425 3434
3426 3435
3427 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) { 3436 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) {
3428 if (slot->type() == Slot::LOOKUP) { 3437 if (slot->type() == Slot::LOOKUP) {
3429 ASSERT(slot->var()->is_dynamic()); 3438 ASSERT(slot->var()->is_dynamic());
3430 3439
3431 // For now, just do a runtime call. 3440 // For now, just do a runtime call. Since the call is inevitable,
3432 frame_->Push(esi); 3441 // we eagerly sync the virtual frame so we can directly push the
3433 frame_->Push(slot->var()->name()); 3442 // arguments into place.
3443 frame_->SyncRange(0, frame_->element_count() - 1);
3444
3445 frame_->EmitPush(esi);
3446 frame_->EmitPush(Immediate(slot->var()->name()));
3434 3447
3435 Result value; 3448 Result value;
3436 if (init_state == CONST_INIT) { 3449 if (init_state == CONST_INIT) {
3437 // Same as the case for a normal store, but ignores attribute 3450 // Same as the case for a normal store, but ignores attribute
3438 // (e.g. READ_ONLY) of context slot so that we can initialize const 3451 // (e.g. READ_ONLY) of context slot so that we can initialize const
3439 // properties (introduced via eval("const foo = (some expr);")). Also, 3452 // properties (introduced via eval("const foo = (some expr);")). Also,
3440 // uses the current function context instead of the top context. 3453 // uses the current function context instead of the top context.
3441 // 3454 //
3442 // Note that we must declare the foo upon entry of eval(), via a 3455 // Note that we must declare the foo upon entry of eval(), via a
3443 // context slot declaration, but we cannot initialize it at the same 3456 // context slot declaration, but we cannot initialize it at the same
(...skipping 610 matching lines...) Expand 10 before | Expand all | Expand 10 after
4054 frame_->RestoreContextRegister(); 4067 frame_->RestoreContextRegister();
4055 // Replace the function on the stack with the result. 4068 // Replace the function on the stack with the result.
4056 frame_->SetElementAt(0, &result); 4069 frame_->SetElementAt(0, &result);
4057 4070
4058 } else if (var != NULL && var->slot() != NULL && 4071 } else if (var != NULL && var->slot() != NULL &&
4059 var->slot()->type() == Slot::LOOKUP) { 4072 var->slot()->type() == Slot::LOOKUP) {
4060 // ---------------------------------- 4073 // ----------------------------------
4061 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj 4074 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj
4062 // ---------------------------------- 4075 // ----------------------------------
4063 4076
4064 // Load the function 4077 // Load the function from the context. Sync the frame so we can
4065 frame_->Push(esi); 4078 // push the arguments directly into place.
4066 frame_->Push(var->name()); 4079 frame_->SyncRange(0, frame_->element_count() - 1);
4080 frame_->EmitPush(esi);
4081 frame_->EmitPush(Immediate(var->name()));
4067 frame_->CallRuntime(Runtime::kLoadContextSlot, 2); 4082 frame_->CallRuntime(Runtime::kLoadContextSlot, 2);
4068 // eax: slot value; edx: receiver 4083 // The runtime call returns a pair of values in eax and edx. The
4084 // looked-up function is in eax and the receiver is in edx. These
4085 // register references are not ref counted here. We spill them
4086 // eagerly since they are arguments to an inevitable call (and are
4087 // not sharable by the arguments).
4088 ASSERT(!allocator()->is_used(eax));
4089 frame_->EmitPush(eax);
4069 4090
4070 // Load the receiver. 4091 // Load the receiver.
4071 frame_->Push(eax); 4092 ASSERT(!allocator()->is_used(edx));
4072 frame_->Push(edx); 4093 frame_->EmitPush(edx);
4073 4094
4074 // Call the function. 4095 // Call the function.
4075 CallWithArguments(args, node->position()); 4096 CallWithArguments(args, node->position());
4076 4097
4077 } else if (property != NULL) { 4098 } else if (property != NULL) {
4078 // Check if the key is a literal string. 4099 // Check if the key is a literal string.
4079 Literal* literal = property->key()->AsLiteral(); 4100 Literal* literal = property->key()->AsLiteral();
4080 4101
4081 if (literal != NULL && literal->handle()->IsSymbol()) { 4102 if (literal != NULL && literal->handle()->IsSymbol()) {
4082 // ------------------------------------------------------------------ 4103 // ------------------------------------------------------------------
(...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after
4631 Slot* slot = variable->slot(); 4652 Slot* slot = variable->slot();
4632 if (variable->is_global()) { 4653 if (variable->is_global()) {
4633 LoadGlobal(); 4654 LoadGlobal();
4634 frame_->Push(variable->name()); 4655 frame_->Push(variable->name());
4635 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, 4656 Result answer = frame_->InvokeBuiltin(Builtins::DELETE,
4636 CALL_FUNCTION, 2); 4657 CALL_FUNCTION, 2);
4637 frame_->Push(&answer); 4658 frame_->Push(&answer);
4638 return; 4659 return;
4639 4660
4640 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 4661 } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
4641 // lookup the context holding the named variable 4662 // Call the runtime to look up the context holding the named
4642 frame_->Push(esi); 4663 // variable. Sync the virtual frame eagerly so we can push the
4643 frame_->Push(variable->name()); 4664 // arguments directly into place.
4665 frame_->SyncRange(0, frame_->element_count() - 1);
4666 frame_->EmitPush(esi);
4667 frame_->EmitPush(Immediate(variable->name()));
4644 Result context = frame_->CallRuntime(Runtime::kLookupContext, 2); 4668 Result context = frame_->CallRuntime(Runtime::kLookupContext, 2);
4645 frame_->Push(&context); 4669 ASSERT(context.is_register());
4646 frame_->Push(variable->name()); 4670 frame_->EmitPush(context.reg());
4671 context.Unuse();
4672 frame_->EmitPush(Immediate(variable->name()));
4647 Result answer = frame_->InvokeBuiltin(Builtins::DELETE, 4673 Result answer = frame_->InvokeBuiltin(Builtins::DELETE,
4648 CALL_FUNCTION, 2); 4674 CALL_FUNCTION, 2);
4649 frame_->Push(&answer); 4675 frame_->Push(&answer);
4650 return; 4676 return;
4651 } 4677 }
4652 4678
4653 // Default: Result of deleting non-global, not dynamically 4679 // Default: Result of deleting non-global, not dynamically
4654 // introduced variables is false. 4680 // introduced variables is false.
4655 frame_->Push(Factory::false_value()); 4681 frame_->Push(Factory::false_value());
4656 4682
(...skipping 2622 matching lines...) Expand 10 before | Expand all | Expand 10 after
7279 7305
7280 // Slow-case: Go through the JavaScript implementation. 7306 // Slow-case: Go through the JavaScript implementation.
7281 __ bind(&slow); 7307 __ bind(&slow);
7282 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 7308 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
7283 } 7309 }
7284 7310
7285 7311
7286 #undef __ 7312 #undef __
7287 7313
7288 } } // namespace v8::internal 7314 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698