// All extension objects were empty and it is safe to use a global
// load IC call.
- Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
- // Load the global object.
LoadGlobal();
- // Setup the name register. All non-reserved registers are available.
- Result name = allocator_->Allocate(ecx);
- ASSERT(name.is_valid());
- __ mov(name.reg(), slot->var()->name());
- RelocInfo::Mode rmode = (typeof_state == INSIDE_TYPEOF)
- ? RelocInfo::CODE_TARGET
- : RelocInfo::CODE_TARGET_CONTEXT;
- Result answer = frame_->CallCodeObject(ic, rmode, &name, 0);
+ frame_->Push(slot->var()->name());
+ RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
+ ? RelocInfo::CODE_TARGET
+ : RelocInfo::CODE_TARGET_CONTEXT;
+ Result answer = frame_->CallLoadIC(mode);
// Discard the global object. The result is in answer.
frame_->Drop();
// else fall through.
case ObjectLiteral::Property::COMPUTED: {
Handle<Object> key(property->key()->handle());
- Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
if (key->IsSymbol()) {
// Duplicate the object as the IC receiver.
frame_->Dup();
Load(property->value());
- Result value = frame_->Pop();
- value.ToRegister(eax);
-
- Result name = allocator_->Allocate(ecx);
- ASSERT(name.is_valid());
- __ Set(name.reg(), Immediate(key));
- Result ignored =
- frame_->CallCodeObject(ic, RelocInfo::CODE_TARGET,
- &value, &name, 0);
+ frame_->Push(key);
+ Result ignored = frame_->CallStoreIC();
// Drop the duplicated receiver and ignore the result.
frame_->Drop();
break;
void DeferredReferenceGetKeyedValue::Generate() {
CodeGenerator* cgen = generator();
- Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
Result receiver(cgen);
Result key(cgen);
enter()->Bind(&receiver, &key);
// it in the IC initialization code and patch the cmp instruction.
// This means that we cannot allow test instructions after calls to
// KeyedLoadIC stubs in other places.
- Result value(cgen);
- if (is_global_) {
- value = cgen->frame()->CallCodeObject(ic,
- RelocInfo::CODE_TARGET_CONTEXT,
- 0);
- } else {
- value = cgen->frame()->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
- }
+ RelocInfo::Mode mode = is_global_
+ ? RelocInfo::CODE_TARGET_CONTEXT
+ : RelocInfo::CODE_TARGET;
+ Result value = cgen->frame()->CallKeyedLoadIC(mode);
// The result needs to be specifically the eax register because the
// offset to the patch site will be expected in a test eax
// instruction.
// thrown below, we must distinguish between the two kinds of
// loads (typeof expression loads must not throw a reference
// error).
- VirtualFrame* frame = cgen_->frame();
Comment cmnt(masm, "[ Load from named Property");
- Handle<String> name(GetName());
+ cgen_->frame()->Push(GetName());
+
Variable* var = expression_->AsVariableProxy()->AsVariable();
- Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
- // Setup the name register.
- Result name_reg = cgen_->allocator()->Allocate(ecx);
- ASSERT(name_reg.is_valid());
- __ mov(name_reg.reg(), name);
ASSERT(var == NULL || var->is_global());
- RelocInfo::Mode rmode = (var == NULL)
- ? RelocInfo::CODE_TARGET
- : RelocInfo::CODE_TARGET_CONTEXT;
- Result answer = frame->CallCodeObject(ic, rmode, &name_reg, 0);
- frame->Push(&answer);
+ RelocInfo::Mode mode = (var == NULL)
+ ? RelocInfo::CODE_TARGET
+ : RelocInfo::CODE_TARGET_CONTEXT;
+ Result answer = cgen_->frame()->CallLoadIC(mode);
+ cgen_->frame()->Push(&answer);
break;
}
cgen_->frame()->Push(&value);
} else {
- VirtualFrame* frame = cgen_->frame();
Comment cmnt(masm, "[ Load from keyed Property");
- Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
- RelocInfo::Mode rmode = is_global
- ? RelocInfo::CODE_TARGET_CONTEXT
- : RelocInfo::CODE_TARGET;
- Result answer = frame->CallCodeObject(ic, rmode, 0);
+ RelocInfo::Mode mode = is_global
+ ? RelocInfo::CODE_TARGET_CONTEXT
+ : RelocInfo::CODE_TARGET;
+ Result answer = cgen_->frame()->CallKeyedLoadIC(mode);
// Make sure that we do not have a test instruction after the
// call. A test instruction after the call is used to
// indicate that we have generated an inline version of the
// keyed load. The explicit nop instruction is here because
// the push that follows might be peep-hole optimized away.
__ nop();
- frame->Push(&answer);
+ cgen_->frame()->Push(&answer);
}
break;
}
void Reference::SetValue(InitState init_state) {
ASSERT(cgen_->HasValidEntryRegisters());
ASSERT(!is_illegal());
- MacroAssembler* masm = cgen_->masm();
- VirtualFrame* frame = cgen_->frame();
switch (type_) {
case SLOT: {
- Comment cmnt(masm, "[ Store to Slot");
+ Comment cmnt(cgen_->masm(), "[ Store to Slot");
Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
ASSERT(slot != NULL);
cgen_->StoreToSlot(slot, init_state);
}
case NAMED: {
- Comment cmnt(masm, "[ Store to named Property");
- // Call the appropriate IC code.
- Handle<String> name(GetName());
- Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
- // TODO(1222589): Make the IC grab the values from the stack.
- Result argument = frame->Pop();
- argument.ToRegister(eax);
- ASSERT(argument.is_valid());
- Result property_name = cgen_->allocator()->Allocate(ecx);
- ASSERT(property_name.is_valid());
- // Setup the name register.
- __ mov(property_name.reg(), name);
- Result answer = frame->CallCodeObject(ic, RelocInfo::CODE_TARGET,
- &argument, &property_name, 0);
- frame->Push(&answer);
+ Comment cmnt(cgen_->masm(), "[ Store to named Property");
+ cgen_->frame()->Push(GetName());
+ Result answer = cgen_->frame()->CallStoreIC();
+ cgen_->frame()->Push(&answer);
break;
}
case KEYED: {
- Comment cmnt(masm, "[ Store to keyed Property");
- // Call IC code.
- Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
- // TODO(1222589): Make the IC grab the values from the stack.
- Result arg = frame->Pop();
- arg.ToRegister(eax);
- ASSERT(arg.is_valid());
- Result answer = frame->CallCodeObject(ic, RelocInfo::CODE_TARGET,
- &arg, 0);
- frame->Push(&answer);
+ Comment cmnt(cgen_->masm(), "[ Store to keyed Property");
+ Result answer = cgen_->frame()->CallKeyedStoreIC();
+ cgen_->frame()->Push(&answer);
break;
}
}
-Result VirtualFrame::CallCodeObject(Handle<Code> code,
- RelocInfo::Mode rmode,
- Result* arg,
- int dropped_args) {
- int spilled_args = 0;
- switch (code->kind()) {
- case Code::LOAD_IC:
- ASSERT(arg->reg().is(ecx));
- ASSERT(dropped_args == 0);
- spilled_args = 1;
- break;
- case Code::KEYED_STORE_IC:
- ASSERT(arg->reg().is(eax));
- ASSERT(dropped_args == 0);
- spilled_args = 2;
- break;
- default:
- // No other types of code objects are called with values
- // in exactly one register.
- UNREACHABLE();
- break;
+Result VirtualFrame::CallLoadIC(RelocInfo::Mode mode) {
+ // Name and receiver are on the top of the frame. The IC expects
+ // name in ecx and receiver on the stack. It does not drop the
+ // receiver.
+ Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+ Result name = Pop();
+ PrepareForCall(1, 0); // One stack arg, not callee-dropped.
+ name.ToRegister(ecx);
+ name.Unuse();
+ return RawCallCodeObject(ic, mode);
+}
+
+
+Result VirtualFrame::CallKeyedLoadIC(RelocInfo::Mode mode) {
+ // Key and receiver are on top of the frame. The IC expects them on
+ // the stack. It does not drop them.
+ Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+ PrepareForCall(2, 0); // Two stack args, neither callee-dropped.
+ return RawCallCodeObject(ic, mode);
+}
+
+
+Result VirtualFrame::CallStoreIC() {
+ // Name, value, and receiver are on top of the frame. The IC
+ // expects name in ecx, value in eax, and receiver on the stack. It
+ // does not drop the receiver.
+ Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+ Result name = Pop();
+ Result value = Pop();
+ PrepareForCall(1, 0); // One stack arg, not callee-dropped.
+
+ if (value.is_register() && value.reg().is(ecx)) {
+ if (name.is_register() && name.reg().is(eax)) {
+ // Wrong registers.
+ __ xchg(eax, ecx);
+ } else {
+ // Register eax is free for value, which frees ecx for name.
+ value.ToRegister(eax);
+ name.ToRegister(ecx);
+ }
+ } else {
+ // Register ecx is free for name, which guarantees eax is free for
+ // value.
+ name.ToRegister(ecx);
+ value.ToRegister(eax);
}
- PrepareForCall(spilled_args, dropped_args);
- arg->Unuse();
- return RawCallCodeObject(code, rmode);
+
+ name.Unuse();
+ value.Unuse();
+ return RawCallCodeObject(ic, RelocInfo::CODE_TARGET);
+}
+
+
+Result VirtualFrame::CallKeyedStoreIC() {
+ // Value, key, and receiver are on the top of the frame. The IC
+ // expects value in eax and key and receiver on the stack. It does
+ // not drop the key and receiver.
+ Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+ // TODO(1222589): Make the IC grab the values from the stack.
+ Result value = Pop();
+ PrepareForCall(2, 0); // Two stack args, neither callee-dropped.
+ value.ToRegister(eax);
+ value.Unuse();
+ return RawCallCodeObject(ic, RelocInfo::CODE_TARGET);
}
int dropped_args) {
int spilled_args = 1;
switch (code->kind()) {
- case Code::STORE_IC:
- ASSERT(arg0->reg().is(eax));
- ASSERT(arg1->reg().is(ecx));
- ASSERT(dropped_args == 0);
- spilled_args = 1;
- break;
case Code::BUILTIN:
ASSERT(*code == Builtins::builtin(Builtins::JSConstructCall));
ASSERT(arg0->reg().is(eax));
InvokeFlag flag,
int frame_arg_count);
- // Call into a JS code object, given the number of arguments it
- // removes from the top of the physical frame.
- // Register arguments are passed as results and consumed by the call.
+ // Call into a call IC or a JS code object given the number of
+ // arguments it drops from the top of the stack. Arguments passed
+ // in registers are given as results and invalidated by the call.
Result CallCodeObject(Handle<Code> ic,
RelocInfo::Mode rmode,
int dropped_args);
Result CallCodeObject(Handle<Code> ic,
RelocInfo::Mode rmode,
- Result* arg,
- int dropped_args);
- Result CallCodeObject(Handle<Code> ic,
- RelocInfo::Mode rmode,
Result* arg0,
Result* arg1,
int dropped_args);
+ // Call load IC. Name and receiver are found on top of the frame.
+ // Receiver is not dropped.
+ Result CallLoadIC(RelocInfo::Mode mode);
+
+ // Call keyed load IC. Key and receiver are found on top of the
+ // frame. They are not dropped.
+ Result CallKeyedLoadIC(RelocInfo::Mode mode);
+
+ // Call store IC. Name, value, and receiver are found on top of the
+ // frame. Receiver is not dropped.
+ Result CallStoreIC();
+
+ // Call keyed store IC. Value, key, and receiver are found on top
+ // of the frame. Key and receiver are not dropped.
+ Result CallKeyedStoreIC();
+
// Drop a number of elements from the top of the expression stack. May
// emit code to affect the physical frame. Does not clobber any registers
// excepting possibly the stack pointer.