void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
Comment cmnt(masm_, "[ ForInStatement");
- int slot = stmt->ForInFeedbackSlot();
+ FeedbackVectorSlot slot = stmt->ForInFeedbackSlot();
SetStatementPosition(stmt);
Label loop, exit;
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
__ mov(a0, v0);
__ bind(&done_convert);
+ PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
__ push(a0);
// Check for proxies.
__ bind(&call_runtime);
__ push(a0); // Duplicate the enumerable object on the stack.
__ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
+ PrepareForBailoutForId(stmt->EnumId(), TOS_REG);
// If we got a map from the runtime call, we can do a fast
// modification check. Otherwise, we got a fixed array, and we have
__ li(a1, FeedbackVector());
__ li(a2, Operand(TypeFeedbackVector::MegamorphicSentinel(isolate())));
- __ sw(a2, FieldMemOperand(a1, FixedArray::OffsetOfElementAt(slot)));
+ int vector_index = FeedbackVector()->GetIndex(slot);
+ __ sw(a2, FieldMemOperand(a1, FixedArray::OffsetOfElementAt(vector_index)));
__ li(a1, Operand(Smi::FromInt(1))); // Smi indicates slow check
__ lw(a2, MemOperand(sp, 0 * kPointerSize)); // Get enumerated object
Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
__ li(LoadDescriptor::NameRegister(), home_object_symbol);
- CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
+ if (FLAG_vector_ics) {
+ __ li(VectorLoadICDescriptor::SlotRegister(),
+ Operand(SmiFromSlot(expr->HomeObjectFeedbackSlot())));
+ CallLoadIC(NOT_CONTEXTUAL);
+ } else {
+ CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
+ }
Label done;
__ Branch(&done, ne, v0, Operand(isolate()->factory()->undefined_value()));
__ li(LoadDescriptor::NameRegister(), Operand(proxy->var()->name()));
if (FLAG_vector_ics) {
__ li(VectorLoadICDescriptor::SlotRegister(),
- Operand(Smi::FromInt(proxy->VariableFeedbackSlot())));
+ Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
}
ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
__ li(LoadDescriptor::NameRegister(), Operand(var->name()));
if (FLAG_vector_ics) {
__ li(VectorLoadICDescriptor::SlotRegister(),
- Operand(Smi::FromInt(proxy->VariableFeedbackSlot())));
+ Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
}
CallLoadIC(CONTEXTUAL);
context()->Plug(v0);
FastCloneShallowObjectStub stub(isolate(), properties_count);
__ CallStub(&stub);
}
+ PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
// If result_saved is true the result is on top of the stack. If
// result_saved is false the result is in v0.
DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
// Fall through.
case ObjectLiteral::Property::COMPUTED:
+ // It is safe to use [[Put]] here because the boilerplate already
+ // contains computed properties with an uninitialized value.
if (key->value()->IsInternalizedString()) {
if (property->emit_store()) {
VisitForAccumulatorValue(value);
__ push(a0);
VisitForStackValue(value);
if (property->emit_store()) {
- __ CallRuntime(Runtime::kSetPrototype, 2);
+ __ CallRuntime(Runtime::kInternalSetPrototype, 2);
} else {
__ Drop(2);
}
Comment cmnt(masm_, "[ Assignment");
- // Left-hand side can only be a property, a global or a (parameter or local)
- // slot.
- enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
- LhsKind assign_type = VARIABLE;
Property* property = expr->target()->AsProperty();
- if (property != NULL) {
- assign_type = (property->key()->IsPropertyName())
- ? NAMED_PROPERTY
- : KEYED_PROPERTY;
- }
+ LhsKind assign_type = GetAssignType(property);
// Evaluate LHS expression.
switch (assign_type) {
VisitForStackValue(property->obj());
}
break;
+ case NAMED_SUPER_PROPERTY:
+ VisitForStackValue(property->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(property->obj()->AsSuperReference());
+ __ Push(result_register());
+ if (expr->is_compound()) {
+ const Register scratch = a1;
+ __ lw(scratch, MemOperand(sp, kPointerSize));
+ __ Push(scratch, result_register());
+ }
+ break;
+ case KEYED_SUPER_PROPERTY: {
+ const Register scratch = a1;
+ VisitForStackValue(property->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(property->obj()->AsSuperReference());
+ __ Move(scratch, result_register());
+ VisitForAccumulatorValue(property->key());
+ __ Push(scratch, result_register());
+ if (expr->is_compound()) {
+ const Register scratch1 = t0;
+ __ lw(scratch1, MemOperand(sp, 2 * kPointerSize));
+ __ Push(scratch1, scratch, result_register());
+ }
+ break;
+ }
case KEYED_PROPERTY:
// We need the key and receiver on both the stack and in v0 and a1.
if (expr->is_compound()) {
EmitNamedPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
+ case NAMED_SUPER_PROPERTY:
+ EmitNamedSuperPropertyLoad(property);
+ PrepareForBailoutForId(property->LoadId(), TOS_REG);
+ break;
+ case KEYED_SUPER_PROPERTY:
+ EmitKeyedSuperPropertyLoad(property);
+ PrepareForBailoutForId(property->LoadId(), TOS_REG);
+ break;
case KEYED_PROPERTY:
EmitKeyedPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
case NAMED_PROPERTY:
EmitNamedPropertyAssignment(expr);
break;
+ case NAMED_SUPER_PROPERTY:
+ EmitNamedSuperPropertyStore(property);
+ context()->Plug(v0);
+ break;
+ case KEYED_SUPER_PROPERTY:
+ EmitKeyedSuperPropertyStore(property);
+ context()->Plug(v0);
+ break;
case KEYED_PROPERTY:
EmitKeyedPropertyAssignment(expr);
break;
__ lw(load_name, MemOperand(sp, 2 * kPointerSize));
if (FLAG_vector_ics) {
__ li(VectorLoadICDescriptor::SlotRegister(),
- Operand(Smi::FromInt(expr->KeyedLoadFeedbackSlot())));
+ Operand(SmiFromSlot(expr->KeyedLoadFeedbackSlot())));
}
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
CallIC(ic, TypeFeedbackId::None());
__ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
if (FLAG_vector_ics) {
__ li(VectorLoadICDescriptor::SlotRegister(),
- Operand(Smi::FromInt(expr->DoneFeedbackSlot())));
+ Operand(SmiFromSlot(expr->DoneFeedbackSlot())));
}
CallLoadIC(NOT_CONTEXTUAL); // v0=result.done
__ mov(a0, v0);
__ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value"
if (FLAG_vector_ics) {
__ li(VectorLoadICDescriptor::SlotRegister(),
- Operand(Smi::FromInt(expr->ValueFeedbackSlot())));
+ Operand(SmiFromSlot(expr->ValueFeedbackSlot())));
}
CallLoadIC(NOT_CONTEXTUAL); // v0=result.value
context()->DropAndPlug(2, v0); // drop iter and g
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
SetSourcePosition(prop->position());
Literal* key = prop->key()->AsLiteral();
+ DCHECK(!prop->IsSuperAccess());
__ li(LoadDescriptor::NameRegister(), Operand(key->value()));
if (FLAG_vector_ics) {
__ li(VectorLoadICDescriptor::SlotRegister(),
- Operand(Smi::FromInt(prop->PropertyFeedbackSlot())));
+ Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
CallLoadIC(NOT_CONTEXTUAL);
} else {
CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
+ // Stack: receiver, home_object.
SetSourcePosition(prop->position());
Literal* key = prop->key()->AsLiteral();
DCHECK(!key->value()->IsSmi());
DCHECK(prop->IsSuperAccess());
- SuperReference* super_ref = prop->obj()->AsSuperReference();
- EmitLoadHomeObject(super_ref);
- __ Push(v0);
- VisitForStackValue(super_ref->this_var());
__ Push(key->value());
__ CallRuntime(Runtime::kLoadFromSuper, 3);
}
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
if (FLAG_vector_ics) {
__ li(VectorLoadICDescriptor::SlotRegister(),
- Operand(Smi::FromInt(prop->PropertyFeedbackSlot())));
+ Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
CallIC(ic);
} else {
CallIC(ic, prop->PropertyFeedbackId());
}
+void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
+ // Stack: receiver, home_object, key.
+ SetSourcePosition(prop->position());
+
+ __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+}
+
+
void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
Token::Value op,
OverwriteMode mode,
}
+void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
+ // Constructor is in v0.
+ DCHECK(lit != NULL);
+ __ push(v0);
+
+ // No access check is needed here since the constructor is created by the
+ // class literal.
+ Register scratch = a1;
+ __ lw(scratch,
+ FieldMemOperand(v0, JSFunction::kPrototypeOrInitialMapOffset));
+ __ push(scratch);
+
+ for (int i = 0; i < lit->properties()->length(); i++) {
+ ObjectLiteral::Property* property = lit->properties()->at(i);
+ Literal* key = property->key()->AsLiteral();
+ Expression* value = property->value();
+ DCHECK(key != NULL);
+
+ if (property->is_static()) {
+ __ lw(scratch, MemOperand(sp, kPointerSize)); // constructor
+ } else {
+ __ lw(scratch, MemOperand(sp, 0)); // prototype
+ }
+ __ push(scratch);
+ VisitForStackValue(key);
+ VisitForStackValue(value);
+
+ switch (property->kind()) {
+ case ObjectLiteral::Property::CONSTANT:
+ case ObjectLiteral::Property::MATERIALIZED_LITERAL:
+ case ObjectLiteral::Property::COMPUTED:
+ case ObjectLiteral::Property::PROTOTYPE:
+ __ CallRuntime(Runtime::kDefineClassMethod, 3);
+ break;
+
+ case ObjectLiteral::Property::GETTER:
+ __ CallRuntime(Runtime::kDefineClassGetter, 3);
+ break;
+
+ case ObjectLiteral::Property::SETTER:
+ __ CallRuntime(Runtime::kDefineClassSetter, 3);
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ // prototype
+ __ CallRuntime(Runtime::kToFastProperties, 1);
+
+ // constructor
+ __ CallRuntime(Runtime::kToFastProperties, 1);
+}
+
+
void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
Token::Value op,
OverwriteMode mode) {
void FullCodeGenerator::EmitAssignment(Expression* expr) {
DCHECK(expr->IsValidReferenceExpression());
- // Left-hand side can only be a property, a global or a (parameter or local)
- // slot.
- enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
- LhsKind assign_type = VARIABLE;
Property* prop = expr->AsProperty();
- if (prop != NULL) {
- assign_type = (prop->key()->IsPropertyName())
- ? NAMED_PROPERTY
- : KEYED_PROPERTY;
- }
+ LhsKind assign_type = GetAssignType(prop);
switch (assign_type) {
case VARIABLE: {
CallStoreIC();
break;
}
+ case NAMED_SUPER_PROPERTY: {
+ __ Push(v0);
+ VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(prop->obj()->AsSuperReference());
+ // stack: value, this; v0: home_object
+ Register scratch = a2;
+ Register scratch2 = a3;
+ __ mov(scratch, result_register()); // home_object
+ __ lw(v0, MemOperand(sp, kPointerSize)); // value
+ __ lw(scratch2, MemOperand(sp, 0)); // this
+ __ sw(scratch2, MemOperand(sp, kPointerSize)); // this
+ __ sw(scratch, MemOperand(sp, 0)); // home_object
+ // stack: this, home_object; v0: value
+ EmitNamedSuperPropertyStore(prop);
+ break;
+ }
+ case KEYED_SUPER_PROPERTY: {
+ __ Push(v0);
+ VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(prop->obj()->AsSuperReference());
+ __ Push(result_register());
+ VisitForAccumulatorValue(prop->key());
+ Register scratch = a2;
+ Register scratch2 = a3;
+ __ lw(scratch2, MemOperand(sp, 2 * kPointerSize)); // value
+ // stack: value, this, home_object; v0: key, a3: value
+ __ lw(scratch, MemOperand(sp, kPointerSize)); // this
+ __ sw(scratch, MemOperand(sp, 2 * kPointerSize));
+ __ lw(scratch, MemOperand(sp, 0)); // home_object
+ __ sw(scratch, MemOperand(sp, kPointerSize));
+ __ sw(v0, MemOperand(sp, 0));
+ __ Move(v0, scratch2);
+ // stack: this, home_object, key; v0: value.
+ EmitKeyedSuperPropertyStore(prop);
+ break;
+ }
case KEYED_PROPERTY: {
__ push(result_register()); // Preserve value.
VisitForStackValue(prop->obj());
}
+void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) {
+ // Assignment to named property of super.
+ // v0 : value
+ // stack : receiver ('this'), home_object
+ DCHECK(prop != NULL);
+ Literal* key = prop->key()->AsLiteral();
+ DCHECK(key != NULL);
+
+ __ Push(key->value());
+ __ Push(v0);
+ __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict
+ : Runtime::kStoreToSuper_Sloppy),
+ 4);
+}
+
+
+void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) {
+ // Assignment to named property of super.
+ // v0 : value
+ // stack : receiver ('this'), home_object, key
+ DCHECK(prop != NULL);
+
+ __ Push(v0);
+ __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreKeyedToSuper_Strict
+ : Runtime::kStoreKeyedToSuper_Sloppy),
+ 4);
+}
+
+
void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
// Assignment to a property, using a keyed store IC.
__ Move(LoadDescriptor::ReceiverRegister(), v0);
EmitNamedPropertyLoad(expr);
} else {
+ VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(expr->obj()->AsSuperReference());
+ __ Push(result_register());
EmitNamedSuperPropertyLoad(expr);
}
PrepareForBailoutForId(expr->LoadId(), TOS_REG);
context()->Plug(v0);
} else {
- VisitForStackValue(expr->obj());
- VisitForAccumulatorValue(expr->key());
- __ Move(LoadDescriptor::NameRegister(), v0);
- __ pop(LoadDescriptor::ReceiverRegister());
- EmitKeyedPropertyLoad(expr);
+ if (!expr->IsSuperAccess()) {
+ VisitForStackValue(expr->obj());
+ VisitForAccumulatorValue(expr->key());
+ __ Move(LoadDescriptor::NameRegister(), v0);
+ __ pop(LoadDescriptor::ReceiverRegister());
+ EmitKeyedPropertyLoad(expr);
+ } else {
+ VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(expr->obj()->AsSuperReference());
+ __ Push(result_register());
+ VisitForStackValue(expr->key());
+ EmitKeyedSuperPropertyLoad(expr);
+ }
context()->Plug(v0);
}
}
const Register scratch = a1;
SuperReference* super_ref = prop->obj()->AsSuperReference();
EmitLoadHomeObject(super_ref);
- __ Push(v0);
+ __ mov(scratch, v0);
VisitForAccumulatorValue(super_ref->this_var());
- __ Push(v0);
- __ lw(scratch, MemOperand(sp, kPointerSize));
- __ Push(scratch, v0);
+ __ Push(scratch, v0, v0, scratch);
__ Push(key->value());
// Stack here:
// - home_object
// - this (receiver)
- // - home_object <-- LoadFromSuper will pop here and below.
- // - this (receiver)
+ // - this (receiver) <-- LoadFromSuper will pop here and below.
+ // - home_object
// - key
__ CallRuntime(Runtime::kLoadFromSuper, 3);
}
+void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
+ Expression* callee = expr->expression();
+ DCHECK(callee->IsProperty());
+ Property* prop = callee->AsProperty();
+ DCHECK(prop->IsSuperAccess());
+
+ SetSourcePosition(prop->position());
+ // Load the function from the receiver.
+ const Register scratch = a1;
+ SuperReference* super_ref = prop->obj()->AsSuperReference();
+ EmitLoadHomeObject(super_ref);
+ __ Move(scratch, v0);
+ VisitForAccumulatorValue(super_ref->this_var());
+ __ Push(scratch, v0, v0, scratch);
+ VisitForStackValue(prop->key());
+
+ // Stack here:
+ // - home_object
+ // - this (receiver)
+ // - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
+ // - home_object
+ // - key
+ __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
+
+ // Replace home_object with target function.
+ __ sw(v0, MemOperand(sp, kPointerSize));
+
+ // Stack here:
+ // - target function
+ // - this (receiver)
+ EmitCall(expr, CallICState::METHOD);
+}
+
+
void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
// Load the arguments.
ZoneList<Expression*>* args = expr->arguments();
SetSourcePosition(expr->position());
Handle<Code> ic = CallIC::initialize_stub(
isolate(), arg_count, call_type);
- __ li(a3, Operand(Smi::FromInt(expr->CallFeedbackSlot())));
+ __ li(a3, Operand(SmiFromSlot(expr->CallFeedbackSlot())));
__ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
// Don't assign a type feedback id to the IC, since type feedback is provided
// by the vector above.
}
+void FullCodeGenerator::EmitLoadSuperConstructor(SuperReference* super_ref) {
+ DCHECK(super_ref != NULL);
+ __ lw(a0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+ __ Push(a0);
+ __ CallRuntime(Runtime::kGetPrototype, 1);
+}
+
+
void FullCodeGenerator::VisitCall(Call* expr) {
#ifdef DEBUG
// We want to verify that RecordJSReturnSite gets called on all paths
// v1 (receiver). Touch up the stack with the right values.
__ sw(v0, MemOperand(sp, (arg_count + 1) * kPointerSize));
__ sw(v1, MemOperand(sp, arg_count * kPointerSize));
+
+ PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
}
// Record source position for debugger.
SetSourcePosition(expr->position());
__ Push(context_register(), a2);
__ CallRuntime(Runtime::kLoadLookupSlot, 2);
__ Push(v0, v1); // Function, receiver.
+ PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
// If fast case code has been generated, emit code to push the
// function and receiver and have the slow path jump around this
} else if (call_type == Call::PROPERTY_CALL) {
Property* property = callee->AsProperty();
bool is_named_call = property->key()->IsPropertyName();
- // super.x() is handled in EmitCallWithLoadIC.
- if (property->IsSuperAccess() && is_named_call) {
- EmitSuperCallWithLoadIC(expr);
+ if (property->IsSuperAccess()) {
+ if (is_named_call) {
+ EmitSuperCallWithLoadIC(expr);
+ } else {
+ EmitKeyedSuperCallWithLoadIC(expr);
+ }
} else {
{
PreservePositionScope scope(masm()->positions_recorder());
EmitKeyedCallWithLoadIC(expr, property->key());
}
}
+ } else if (call_type == Call::SUPER_CALL) {
+ SuperReference* super_ref = callee->AsSuperReference();
+ EmitLoadSuperConstructor(super_ref);
+ __ Push(result_register());
+ VisitForStackValue(super_ref->this_var());
+ EmitCall(expr, CallICState::METHOD);
} else {
DCHECK(call_type == Call::OTHER_CALL);
// Call to an arbitrary expression not handled specially above.
// Push constructor on the stack. If it's not a function it's used as
// receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
// ignored.
- VisitForStackValue(expr->expression());
+ if (expr->expression()->IsSuperReference()) {
+ EmitLoadSuperConstructor(expr->expression()->AsSuperReference());
+ __ Push(result_register());
+ } else {
+ VisitForStackValue(expr->expression());
+ }
// Push the arguments ("left-to-right") on the stack.
ZoneList<Expression*>* args = expr->arguments();
// Record call targets in unoptimized code.
if (FLAG_pretenuring_call_new) {
EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot());
- DCHECK(expr->AllocationSiteFeedbackSlot() ==
- expr->CallNewFeedbackSlot() + 1);
+ DCHECK(expr->AllocationSiteFeedbackSlot().ToInt() ==
+ expr->CallNewFeedbackSlot().ToInt() + 1);
}
__ li(a2, FeedbackVector());
- __ li(a3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot())));
+ __ li(a3, Operand(SmiFromSlot(expr->CallNewFeedbackSlot())));
CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET);
__ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
}
+void FullCodeGenerator::EmitIsJSProxy(CallRuntime* expr) {
+ ZoneList<Expression*>* args = expr->arguments();
+ DCHECK(args->length() == 1);
+
+ VisitForAccumulatorValue(args->at(0));
+
+ Label materialize_true, materialize_false;
+ Label* if_true = NULL;
+ Label* if_false = NULL;
+ Label* fall_through = NULL;
+ context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
+ &if_false, &fall_through);
+
+ __ JumpIfSmi(v0, if_false);
+ Register map = a1;
+ Register type_reg = a2;
+ __ GetObjectType(v0, map, type_reg);
+ __ Subu(type_reg, type_reg, Operand(FIRST_JS_PROXY_TYPE));
+ PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+ Split(ls, type_reg, Operand(LAST_JS_PROXY_TYPE - FIRST_JS_PROXY_TYPE),
+ if_true, if_false, fall_through);
+
+ context()->Plug(if_true, if_false);
+}
+
+
void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
DCHECK(expr->arguments()->length() == 0);
__ li(LoadDescriptor::NameRegister(), Operand(expr->name()));
if (FLAG_vector_ics) {
__ li(VectorLoadICDescriptor::SlotRegister(),
- Operand(Smi::FromInt(expr->CallRuntimeFeedbackSlot())));
+ Operand(SmiFromSlot(expr->CallRuntimeFeedbackSlot())));
CallLoadIC(NOT_CONTEXTUAL);
} else {
CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
Comment cmnt(masm_, "[ CountOperation");
SetSourcePosition(expr->position());
- // Expression can only be a property, a global or a (parameter or local)
- // slot.
- enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
- LhsKind assign_type = VARIABLE;
Property* prop = expr->expression()->AsProperty();
- // In case of a property we use the uninitialized expression context
- // of the key to detect a named property.
- if (prop != NULL) {
- assign_type =
- (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
- }
+ LhsKind assign_type = GetAssignType(prop);
// Evaluate expression and get value.
if (assign_type == VARIABLE) {
__ li(at, Operand(Smi::FromInt(0)));
__ push(at);
}
- if (assign_type == NAMED_PROPERTY) {
- // Put the object both on the stack and in the register.
- VisitForStackValue(prop->obj());
- __ lw(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
- EmitNamedPropertyLoad(prop);
- } else {
- VisitForStackValue(prop->obj());
- VisitForStackValue(prop->key());
- __ lw(LoadDescriptor::ReceiverRegister(),
- MemOperand(sp, 1 * kPointerSize));
- __ lw(LoadDescriptor::NameRegister(), MemOperand(sp, 0));
- EmitKeyedPropertyLoad(prop);
+ switch (assign_type) {
+ case NAMED_PROPERTY: {
+ // Put the object both on the stack and in the register.
+ VisitForStackValue(prop->obj());
+ __ lw(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
+ EmitNamedPropertyLoad(prop);
+ break;
+ }
+
+ case NAMED_SUPER_PROPERTY: {
+ VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(prop->obj()->AsSuperReference());
+ __ Push(result_register());
+ const Register scratch = a1;
+ __ lw(scratch, MemOperand(sp, kPointerSize));
+ __ Push(scratch, result_register());
+ EmitNamedSuperPropertyLoad(prop);
+ break;
+ }
+
+ case KEYED_SUPER_PROPERTY: {
+ VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
+ EmitLoadHomeObject(prop->obj()->AsSuperReference());
+ const Register scratch = a1;
+ const Register scratch1 = t0;
+ __ Move(scratch, result_register());
+ VisitForAccumulatorValue(prop->key());
+ __ Push(scratch, result_register());
+ __ lw(scratch1, MemOperand(sp, 2 * kPointerSize));
+ __ Push(scratch1, scratch, result_register());
+ EmitKeyedSuperPropertyLoad(prop);
+ break;
+ }
+
+ case KEYED_PROPERTY: {
+ VisitForStackValue(prop->obj());
+ VisitForStackValue(prop->key());
+ __ lw(LoadDescriptor::ReceiverRegister(),
+ MemOperand(sp, 1 * kPointerSize));
+ __ lw(LoadDescriptor::NameRegister(), MemOperand(sp, 0));
+ EmitKeyedPropertyLoad(prop);
+ break;
+ }
+
+ case VARIABLE:
+ UNREACHABLE();
}
}
case NAMED_PROPERTY:
__ sw(v0, MemOperand(sp, kPointerSize));
break;
+ case NAMED_SUPER_PROPERTY:
+ __ sw(v0, MemOperand(sp, 2 * kPointerSize));
+ break;
case KEYED_PROPERTY:
__ sw(v0, MemOperand(sp, 2 * kPointerSize));
break;
+ case KEYED_SUPER_PROPERTY:
+ __ sw(v0, MemOperand(sp, 3 * kPointerSize));
+ break;
}
}
}
case NAMED_PROPERTY:
__ sw(v0, MemOperand(sp, kPointerSize));
break;
+ case NAMED_SUPER_PROPERTY:
+ __ sw(v0, MemOperand(sp, 2 * kPointerSize));
+ break;
case KEYED_PROPERTY:
__ sw(v0, MemOperand(sp, 2 * kPointerSize));
break;
+ case KEYED_SUPER_PROPERTY:
+ __ sw(v0, MemOperand(sp, 3 * kPointerSize));
+ break;
}
}
}
}
break;
}
+ case NAMED_SUPER_PROPERTY: {
+ EmitNamedSuperPropertyStore(prop);
+ if (expr->is_postfix()) {
+ if (!context()->IsEffect()) {
+ context()->PlugTOS();
+ }
+ } else {
+ context()->Plug(v0);
+ }
+ break;
+ }
+ case KEYED_SUPER_PROPERTY: {
+ EmitKeyedSuperPropertyStore(prop);
+ if (expr->is_postfix()) {
+ if (!context()->IsEffect()) {
+ context()->PlugTOS();
+ }
+ } else {
+ context()->Plug(v0);
+ }
+ break;
+ }
case KEYED_PROPERTY: {
__ mov(StoreDescriptor::ValueRegister(), result_register());
__ Pop(StoreDescriptor::ReceiverRegister(),
__ li(LoadDescriptor::NameRegister(), Operand(proxy->name()));
if (FLAG_vector_ics) {
__ li(VectorLoadICDescriptor::SlotRegister(),
- Operand(Smi::FromInt(proxy->VariableFeedbackSlot())));
+ Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
}
// Use a regular load, not a contextual load, to avoid a reference
// error.