| OLD | NEW |
| 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 2990 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3001 case ObjectLiteral::Property::CONSTANT: break; | 3001 case ObjectLiteral::Property::CONSTANT: break; |
| 3002 case ObjectLiteral::Property::COMPUTED: { | 3002 case ObjectLiteral::Property::COMPUTED: { |
| 3003 Handle<Object> key(property->key()->handle()); | 3003 Handle<Object> key(property->key()->handle()); |
| 3004 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 3004 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 3005 if (key->IsSymbol()) { | 3005 if (key->IsSymbol()) { |
| 3006 __ mov(eax, frame_->Top()); | 3006 __ mov(eax, frame_->Top()); |
| 3007 frame_->EmitPush(eax); | 3007 frame_->EmitPush(eax); |
| 3008 LoadAndSpill(property->value()); | 3008 LoadAndSpill(property->value()); |
| 3009 frame_->EmitPop(eax); | 3009 frame_->EmitPop(eax); |
| 3010 __ Set(ecx, Immediate(key)); | 3010 __ Set(ecx, Immediate(key)); |
| 3011 frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); | 3011 Result name = allocator()->Allocate(ecx); |
| 3012 ASSERT(name.is_valid()); |
| 3013 Result value = allocator()->Allocate(eax); |
| 3014 ASSERT(value.is_valid()); |
| 3015 frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET, &value, &name, 0); |
| 3012 frame_->Drop(); | 3016 frame_->Drop(); |
| 3013 // Ignore result. | 3017 // Ignore result. |
| 3014 break; | 3018 break; |
| 3015 } | 3019 } |
| 3016 // Fall through | 3020 // Fall through |
| 3017 } | 3021 } |
| 3018 case ObjectLiteral::Property::PROTOTYPE: { | 3022 case ObjectLiteral::Property::PROTOTYPE: { |
| 3019 __ mov(eax, frame_->Top()); | 3023 __ mov(eax, frame_->Top()); |
| 3020 frame_->EmitPush(eax); | 3024 frame_->EmitPush(eax); |
| 3021 LoadAndSpill(property->key()); | 3025 LoadAndSpill(property->key()); |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3342 Load(node->expression()); | 3346 Load(node->expression()); |
| 3343 LoadGlobal(); | 3347 LoadGlobal(); |
| 3344 | 3348 |
| 3345 // Push the arguments ("left-to-right") on the stack. | 3349 // Push the arguments ("left-to-right") on the stack. |
| 3346 ZoneList<Expression*>* args = node->arguments(); | 3350 ZoneList<Expression*>* args = node->arguments(); |
| 3347 int arg_count = args->length(); | 3351 int arg_count = args->length(); |
| 3348 for (int i = 0; i < arg_count; i++) { | 3352 for (int i = 0; i < arg_count; i++) { |
| 3349 Load(args->at(i)); | 3353 Load(args->at(i)); |
| 3350 } | 3354 } |
| 3351 | 3355 |
| 3352 // TODO(205): Get rid of this spilling. It is only necessary because | |
| 3353 // we load the function from the non-virtual stack. | |
| 3354 frame_->SpillAll(); | |
| 3355 | |
| 3356 // Constructors are called with the number of arguments in register | 3356 // Constructors are called with the number of arguments in register |
| 3357 // eax for now. Another option would be to have separate construct | 3357 // eax for now. Another option would be to have separate construct |
| 3358 // call trampolines per different arguments counts encountered. | 3358 // call trampolines per different arguments counts encountered. |
| 3359 __ Set(eax, Immediate(arg_count)); | 3359 Result num_args = allocator()->Allocate(eax); |
| 3360 ASSERT(num_args.is_valid()); |
| 3361 __ Set(num_args.reg(), Immediate(arg_count)); |
| 3360 | 3362 |
| 3361 // Load the function into temporary function slot as per calling | 3363 // Load the function into temporary function slot as per calling |
| 3362 // convention. | 3364 // convention. |
| 3363 __ mov(edi, frame_->ElementAt(arg_count + 1)); | 3365 frame_->PushElementAt(arg_count + 1); |
| 3366 Result function = frame_->Pop(); |
| 3367 function.ToRegister(edi); |
| 3368 ASSERT(function.is_valid()); |
| 3364 | 3369 |
| 3365 // Call the construct call builtin that handles allocation and | 3370 // Call the construct call builtin that handles allocation and |
| 3366 // constructor invocation. | 3371 // constructor invocation. |
| 3367 CodeForSourcePosition(node->position()); | 3372 CodeForSourcePosition(node->position()); |
| 3368 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall)); | 3373 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall)); |
| 3369 Result result = frame_->CallCodeObject(ic, | 3374 Result result = frame_->CallCodeObject(ic, |
| 3370 RelocInfo::CONSTRUCT_CALL, | 3375 RelocInfo::CONSTRUCT_CALL, |
| 3376 &num_args, |
| 3377 &function, |
| 3371 args->length() + 1); | 3378 args->length() + 1); |
| 3372 | 3379 |
| 3373 // Replace the function on the stack with the result. | 3380 // Replace the function on the stack with the result. |
| 3374 frame_->SetElementAt(0, &result); | 3381 frame_->SetElementAt(0, &result); |
| 3375 } | 3382 } |
| 3376 | 3383 |
| 3377 | 3384 |
| 3378 void CodeGenerator::VisitCallEval(CallEval* node) { | 3385 void CodeGenerator::VisitCallEval(CallEval* node) { |
| 3379 VirtualFrame::SpilledScope spilled_scope(this); | 3386 VirtualFrame::SpilledScope spilled_scope(this); |
| 3380 Comment cmnt(masm_, "[ CallEval"); | 3387 Comment cmnt(masm_, "[ CallEval"); |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3717 left.Unuse(); | 3724 left.Unuse(); |
| 3718 true_target()->Branch(equal); | 3725 true_target()->Branch(equal); |
| 3719 false_target()->Jump(); | 3726 false_target()->Jump(); |
| 3720 } | 3727 } |
| 3721 | 3728 |
| 3722 | 3729 |
| 3723 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { | 3730 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { |
| 3724 if (CheckForInlineRuntimeCall(node)) { | 3731 if (CheckForInlineRuntimeCall(node)) { |
| 3725 return; | 3732 return; |
| 3726 } | 3733 } |
| 3727 VirtualFrame::SpilledScope spilled_scope(this); | |
| 3728 | 3734 |
| 3729 ZoneList<Expression*>* args = node->arguments(); | 3735 ZoneList<Expression*>* args = node->arguments(); |
| 3730 Comment cmnt(masm_, "[ CallRuntime"); | 3736 Comment cmnt(masm_, "[ CallRuntime"); |
| 3731 Runtime::Function* function = node->function(); | 3737 Runtime::Function* function = node->function(); |
| 3732 | 3738 |
| 3733 if (function == NULL) { | 3739 if (function == NULL) { |
| 3734 // Prepare stack for calling JS runtime function. | 3740 // Prepare stack for calling JS runtime function. |
| 3735 frame_->EmitPush(Immediate(node->name())); | 3741 frame_->Push(node->name()); |
| 3736 // Push the builtins object found in the current global object. | 3742 // Push the builtins object found in the current global object. |
| 3737 __ mov(edx, GlobalObject()); | 3743 Result temp = allocator()->Allocate(); |
| 3738 frame_->EmitPush(FieldOperand(edx, GlobalObject::kBuiltinsOffset)); | 3744 ASSERT(temp.is_valid()); |
| 3745 __ mov(temp.reg(), GlobalObject()); |
| 3746 __ mov(temp.reg(), FieldOperand(temp.reg(), GlobalObject::kBuiltinsOffset)); |
| 3747 frame_->Push(&temp); |
| 3739 } | 3748 } |
| 3740 | 3749 |
| 3741 // Push the arguments ("left-to-right"). | 3750 // Push the arguments ("left-to-right"). |
| 3742 int arg_count = args->length(); | 3751 int arg_count = args->length(); |
| 3743 for (int i = 0; i < arg_count; i++) { | 3752 for (int i = 0; i < arg_count; i++) { |
| 3744 LoadAndSpill(args->at(i)); | 3753 Load(args->at(i)); |
| 3745 } | 3754 } |
| 3746 | 3755 |
| 3747 if (function == NULL) { | 3756 if (function == NULL) { |
| 3748 // Call the JS runtime function. | 3757 // Call the JS runtime function. |
| 3749 Handle<Code> stub = ComputeCallInitialize(arg_count); | 3758 Handle<Code> stub = ComputeCallInitialize(arg_count); |
| 3750 __ Set(eax, Immediate(args->length())); | 3759 |
| 3751 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); | 3760 Result num_args = allocator()->Allocate(eax); |
| 3761 ASSERT(num_args.is_valid()); |
| 3762 __ Set(num_args.reg(), Immediate(args->length())); |
| 3763 Result answer = frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, |
| 3764 &num_args, arg_count + 1); |
| 3752 frame_->RestoreContextRegister(); | 3765 frame_->RestoreContextRegister(); |
| 3753 __ mov(frame_->Top(), eax); | 3766 frame_->SetElementAt(0, &answer); |
| 3754 } else { | 3767 } else { |
| 3755 // Call the C runtime function. | 3768 // Call the C runtime function. |
| 3756 frame_->CallRuntime(function, arg_count); | 3769 Result answer = frame_->CallRuntime(function, arg_count); |
| 3757 frame_->EmitPush(eax); | 3770 frame_->Push(&answer); |
| 3758 } | 3771 } |
| 3759 } | 3772 } |
| 3760 | 3773 |
| 3761 | 3774 |
| 3762 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { | 3775 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { |
| 3763 // Note that because of NOT and an optimization in comparison of a typeof | 3776 // Note that because of NOT and an optimization in comparison of a typeof |
| 3764 // expression to a literal string, this function can fail to leave a value | 3777 // expression to a literal string, this function can fail to leave a value |
| 3765 // on top of the frame or in the cc register. | 3778 // on top of the frame or in the cc register. |
| 3766 Comment cmnt(masm_, "[ UnaryOperation"); | 3779 Comment cmnt(masm_, "[ UnaryOperation"); |
| 3767 | 3780 |
| (...skipping 764 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4532 } else { | 4545 } else { |
| 4533 Literal* raw_name = property->key()->AsLiteral(); | 4546 Literal* raw_name = property->key()->AsLiteral(); |
| 4534 ASSERT(raw_name != NULL); | 4547 ASSERT(raw_name != NULL); |
| 4535 return Handle<String>(String::cast(*raw_name->handle())); | 4548 return Handle<String>(String::cast(*raw_name->handle())); |
| 4536 } | 4549 } |
| 4537 } | 4550 } |
| 4538 | 4551 |
| 4539 | 4552 |
| 4540 void Reference::GetValue(TypeofState typeof_state) { | 4553 void Reference::GetValue(TypeofState typeof_state) { |
| 4541 ASSERT(!cgen_->in_spilled_code()); | 4554 ASSERT(!cgen_->in_spilled_code()); |
| 4555 ASSERT(cgen_->HasValidEntryRegisters()); |
| 4542 ASSERT(!is_illegal()); | 4556 ASSERT(!is_illegal()); |
| 4543 MacroAssembler* masm = cgen_->masm(); | 4557 MacroAssembler* masm = cgen_->masm(); |
| 4544 switch (type_) { | 4558 switch (type_) { |
| 4545 case SLOT: { | 4559 case SLOT: { |
| 4546 Comment cmnt(masm, "[ Load from Slot"); | 4560 Comment cmnt(masm, "[ Load from Slot"); |
| 4547 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); | 4561 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); |
| 4548 ASSERT(slot != NULL); | 4562 ASSERT(slot != NULL); |
| 4549 cgen_->LoadFromSlot(slot, typeof_state); | 4563 cgen_->LoadFromSlot(slot, typeof_state); |
| 4550 break; | 4564 break; |
| 4551 } | 4565 } |
| 4552 | 4566 |
| 4553 case NAMED: { | 4567 case NAMED: { |
| 4554 // TODO(1241834): Make sure that it is safe to ignore the | 4568 // TODO(1241834): Make sure that it is safe to ignore the |
| 4555 // distinction between expressions in a typeof and not in a | 4569 // distinction between expressions in a typeof and not in a |
| 4556 // typeof. If there is a chance that reference errors can be | 4570 // typeof. If there is a chance that reference errors can be |
| 4557 // thrown below, we must distinguish between the two kinds of | 4571 // thrown below, we must distinguish between the two kinds of |
| 4558 // loads (typeof expression loads must not throw a reference | 4572 // loads (typeof expression loads must not throw a reference |
| 4559 // error). | 4573 // error). |
| 4560 VirtualFrame::SpilledScope spilled_scope(cgen_); | |
| 4561 VirtualFrame* frame = cgen_->frame(); | 4574 VirtualFrame* frame = cgen_->frame(); |
| 4562 Comment cmnt(masm, "[ Load from named Property"); | 4575 Comment cmnt(masm, "[ Load from named Property"); |
| 4563 Handle<String> name(GetName()); | 4576 Handle<String> name(GetName()); |
| 4564 Variable* var = expression_->AsVariableProxy()->AsVariable(); | 4577 Variable* var = expression_->AsVariableProxy()->AsVariable(); |
| 4565 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 4578 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 4566 // Setup the name register. | 4579 // Setup the name register. |
| 4567 __ mov(ecx, name); | 4580 Result name_reg = cgen_->allocator()->Allocate(ecx); |
| 4568 if (var != NULL) { | 4581 ASSERT(name_reg.is_valid()); |
| 4569 ASSERT(var->is_global()); | 4582 __ mov(name_reg.reg(), name); |
| 4570 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0); | 4583 ASSERT(var == NULL || var->is_global()); |
| 4571 } else { | 4584 RelocInfo::Mode rmode = (var == NULL) |
| 4572 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); | 4585 ? RelocInfo::CODE_TARGET |
| 4573 } | 4586 : RelocInfo::CODE_TARGET_CONTEXT; |
| 4574 frame->EmitPush(eax); // IC call leaves result in eax, push it out | 4587 Result answer = frame->CallCodeObject(ic, rmode, &name_reg, 0); |
| 4588 frame->Push(&answer); |
| 4575 break; | 4589 break; |
| 4576 } | 4590 } |
| 4577 | 4591 |
| 4578 case KEYED: { | 4592 case KEYED: { |
| 4579 // TODO(1241834): Make sure that this it is safe to ignore the | 4593 // TODO(1241834): Make sure that this it is safe to ignore the |
| 4580 // distinction between expressions in a typeof and not in a typeof. | 4594 // distinction between expressions in a typeof and not in a typeof. |
| 4581 Comment cmnt(masm, "[ Load from keyed Property"); | 4595 Comment cmnt(masm, "[ Load from keyed Property"); |
| 4582 Variable* var = expression_->AsVariableProxy()->AsVariable(); | 4596 Variable* var = expression_->AsVariableProxy()->AsVariable(); |
| 4583 bool is_global = var != NULL; | 4597 bool is_global = var != NULL; |
| 4584 ASSERT(!is_global || var->is_global()); | 4598 ASSERT(!is_global || var->is_global()); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4654 __ IncrementCounter(&Counters::keyed_load_inline, 1); | 4668 __ IncrementCounter(&Counters::keyed_load_inline, 1); |
| 4655 | 4669 |
| 4656 // Restore the receiver and key to the frame and push the | 4670 // Restore the receiver and key to the frame and push the |
| 4657 // result on top of it. | 4671 // result on top of it. |
| 4658 cgen_->frame()->Push(&receiver); | 4672 cgen_->frame()->Push(&receiver); |
| 4659 cgen_->frame()->Push(&key); | 4673 cgen_->frame()->Push(&key); |
| 4660 deferred->exit()->Bind(&value); | 4674 deferred->exit()->Bind(&value); |
| 4661 cgen_->frame()->Push(&value); | 4675 cgen_->frame()->Push(&value); |
| 4662 | 4676 |
| 4663 } else { | 4677 } else { |
| 4664 VirtualFrame::SpilledScope spilled_scope(cgen_); | |
| 4665 VirtualFrame* frame = cgen_->frame(); | 4678 VirtualFrame* frame = cgen_->frame(); |
| 4666 Comment cmnt(masm, "[ Load from keyed Property"); | 4679 Comment cmnt(masm, "[ Load from keyed Property"); |
| 4667 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 4680 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 4668 if (is_global) { | 4681 RelocInfo::Mode rmode = is_global |
| 4669 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0); | 4682 ? RelocInfo::CODE_TARGET_CONTEXT |
| 4670 } else { | 4683 : RelocInfo::CODE_TARGET; |
| 4671 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); | 4684 Result answer = frame->CallCodeObject(ic, rmode, 0); |
| 4672 } | |
| 4673 // Make sure that we do not have a test instruction after the | 4685 // Make sure that we do not have a test instruction after the |
| 4674 // call. A test instruction after the call is used to | 4686 // call. A test instruction after the call is used to |
| 4675 // indicate that we have generated an inline version of the | 4687 // indicate that we have generated an inline version of the |
| 4676 // keyed load. The explicit nop instruction is here because | 4688 // keyed load. The explicit nop instruction is here because |
| 4677 // the push that follows might be peep-hole optimized away. | 4689 // the push that follows might be peep-hole optimized away. |
| 4678 __ nop(); | 4690 __ nop(); |
| 4679 frame->EmitPush(eax); // IC call leaves result in eax, push it out | 4691 frame->Push(&answer); |
| 4680 } | 4692 } |
| 4681 break; | 4693 break; |
| 4682 } | 4694 } |
| 4683 | 4695 |
| 4684 default: | 4696 default: |
| 4685 UNREACHABLE(); | 4697 UNREACHABLE(); |
| 4686 } | 4698 } |
| 4687 } | 4699 } |
| 4688 | 4700 |
| 4689 | 4701 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 4711 if (slot->type() == Slot::PARAMETER) { | 4723 if (slot->type() == Slot::PARAMETER) { |
| 4712 cgen_->frame()->TakeParameterAt(slot->index()); | 4724 cgen_->frame()->TakeParameterAt(slot->index()); |
| 4713 } else { | 4725 } else { |
| 4714 ASSERT(slot->type() == Slot::LOCAL); | 4726 ASSERT(slot->type() == Slot::LOCAL); |
| 4715 cgen_->frame()->TakeLocalAt(slot->index()); | 4727 cgen_->frame()->TakeLocalAt(slot->index()); |
| 4716 } | 4728 } |
| 4717 } | 4729 } |
| 4718 | 4730 |
| 4719 | 4731 |
| 4720 void Reference::SetValue(InitState init_state) { | 4732 void Reference::SetValue(InitState init_state) { |
| 4733 ASSERT(cgen_->HasValidEntryRegisters()); |
| 4721 ASSERT(!is_illegal()); | 4734 ASSERT(!is_illegal()); |
| 4722 MacroAssembler* masm = cgen_->masm(); | 4735 MacroAssembler* masm = cgen_->masm(); |
| 4723 VirtualFrame* frame = cgen_->frame(); | 4736 VirtualFrame* frame = cgen_->frame(); |
| 4724 switch (type_) { | 4737 switch (type_) { |
| 4725 case SLOT: { | 4738 case SLOT: { |
| 4726 Comment cmnt(masm, "[ Store to Slot"); | 4739 Comment cmnt(masm, "[ Store to Slot"); |
| 4727 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); | 4740 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); |
| 4728 ASSERT(slot != NULL); | 4741 ASSERT(slot != NULL); |
| 4729 cgen_->StoreToSlot(slot, init_state); | 4742 cgen_->StoreToSlot(slot, init_state); |
| 4730 break; | 4743 break; |
| 4731 } | 4744 } |
| 4732 | 4745 |
| 4733 case NAMED: { | 4746 case NAMED: { |
| 4734 VirtualFrame::SpilledScope spilled_scope(cgen_); | |
| 4735 Comment cmnt(masm, "[ Store to named Property"); | 4747 Comment cmnt(masm, "[ Store to named Property"); |
| 4736 // Call the appropriate IC code. | 4748 // Call the appropriate IC code. |
| 4737 Handle<String> name(GetName()); | 4749 Handle<String> name(GetName()); |
| 4738 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 4750 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 4739 // TODO(1222589): Make the IC grab the values from the stack. | 4751 // TODO(1222589): Make the IC grab the values from the stack. |
| 4740 frame->EmitPop(eax); | 4752 Result argument = frame->Pop(); |
| 4753 argument.ToRegister(eax); |
| 4754 ASSERT(argument.is_valid()); |
| 4755 Result property_name = cgen_->allocator()->Allocate(ecx); |
| 4756 ASSERT(property_name.is_valid()); |
| 4741 // Setup the name register. | 4757 // Setup the name register. |
| 4742 __ mov(ecx, name); | 4758 __ mov(property_name.reg(), name); |
| 4743 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); | 4759 Result answer = frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, |
| 4744 frame->EmitPush(eax); // IC call leaves result in eax, push it out | 4760 &argument, &property_name, 0); |
| 4761 frame->Push(&answer); |
| 4745 break; | 4762 break; |
| 4746 } | 4763 } |
| 4747 | 4764 |
| 4748 case KEYED: { | 4765 case KEYED: { |
| 4749 VirtualFrame::SpilledScope spilled_scope(cgen_); | |
| 4750 Comment cmnt(masm, "[ Store to keyed Property"); | 4766 Comment cmnt(masm, "[ Store to keyed Property"); |
| 4751 // Call IC code. | 4767 // Call IC code. |
| 4752 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 4768 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 4753 // TODO(1222589): Make the IC grab the values from the stack. | 4769 // TODO(1222589): Make the IC grab the values from the stack. |
| 4754 frame->EmitPop(eax); | 4770 Result arg = frame->Pop(); |
| 4755 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); | 4771 arg.ToRegister(eax); |
| 4756 frame->EmitPush(eax); // IC call leaves result in eax, push it out | 4772 ASSERT(arg.is_valid()); |
| 4773 Result answer = frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, |
| 4774 &arg, 0); |
| 4775 frame->Push(&answer); |
| 4757 break; | 4776 break; |
| 4758 } | 4777 } |
| 4759 | 4778 |
| 4760 default: | 4779 default: |
| 4761 UNREACHABLE(); | 4780 UNREACHABLE(); |
| 4762 } | 4781 } |
| 4763 } | 4782 } |
| 4764 | 4783 |
| 4765 | 4784 |
| 4766 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined). | 4785 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined). |
| (...skipping 1480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6247 | 6266 |
| 6248 // Slow-case: Go through the JavaScript implementation. | 6267 // Slow-case: Go through the JavaScript implementation. |
| 6249 __ bind(&slow); | 6268 __ bind(&slow); |
| 6250 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 6269 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
| 6251 } | 6270 } |
| 6252 | 6271 |
| 6253 | 6272 |
| 6254 #undef __ | 6273 #undef __ |
| 6255 | 6274 |
| 6256 } } // namespace v8::internal | 6275 } } // namespace v8::internal |
| OLD | NEW |