Allow esi to be an allocatable register on IA32.

Make esi available to the register allocator rather than dedicating it
permanently to the context.

The context is still passed in register esi to JavaScript and to the runtime
as part of the calling convention.  Because some stubs might end up calling
JS or the runtime, it is also conservatively passed to stubs.

Roughly half the calls have been modified to use the context as an input
value in fixed register esi.  The other half are marked as calls or deferred
code so esi is spilled and can be explicitly set.

It is no longer necessary to restore the context to esi after a call that
might change it.

Review URL: http://codereview.chromium.org/6452001

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6713 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 12e62e71
// Copyright 2010 the V8 project authors. All rights reserved.
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
......@@ -281,6 +281,88 @@ void HValue::SetOperandAt(int index, HValue* value) {
}
void HLoadKeyedGeneric::InternalSetOperandAt(int index, HValue* value) {
if (index < 2) {
operands_[index] = value;
} else {
context_ = value;
}
}
void HCallKeyed::InternalSetOperandAt(int index, HValue* value) {
// The key and all the arguments are stored in the base class's arguments_
// vector. The context is in the object itself. Ugly.
if (index <= argument_count()) {
arguments_[index] = value;
} else {
context_ = value;
}
}
void HCallNamed::InternalSetOperandAt(int index, HValue* value) {
// The arguments are in the base class's arguments_ vector. The context
// is in the object itself.
if (index < argument_count()) {
arguments_[index] = value;
} else {
context_ = value;
}
}
void HCallFunction::InternalSetOperandAt(int index, HValue* value) {
// The arguments are in the base class's arguments_ vector. The context
// is in the object itself.
if (index < argument_count()) {
arguments_[index] = value;
} else {
context_ = value;
}
}
void HCallGlobal::InternalSetOperandAt(int index, HValue* value) {
// The arguments are in the base class's arguments_ vector. The context
// is in the object itself.
if (index < argument_count()) {
arguments_[index] = value;
} else {
context_ = value;
}
}
void HCallNew::InternalSetOperandAt(int index, HValue* value) {
// The arguments are in the base class's arguments_ vector. The context
// is in the object itself.
if (index < argument_count()) {
arguments_[index] = value;
} else {
context_ = value;
}
}
void HStoreKeyedGeneric::InternalSetOperandAt(int index, HValue* value) {
if (index < 3) {
operands_[index] = value;
} else {
context_ = value;
}
}
void HStoreNamedGeneric::InternalSetOperandAt(int index, HValue* value) {
if (index < 2) {
operands_[index] = value;
} else {
context_ = value;
}
}
void HValue::ReplaceAndDelete(HValue* other) {
ReplaceValue(other);
Delete();
......@@ -731,13 +813,24 @@ void HCallRuntime::PrintDataTo(StringStream* stream) const {
HCall::PrintDataTo(stream);
}
void HCallStub::PrintDataTo(StringStream* stream) const {
stream->Add("%s(%d)",
HUnaryOperation::PrintDataTo(stream);
stream->Add(" %s(%d)",
CodeStub::MajorName(major_key_, false),
argument_count_);
}
void HInstanceOf::PrintDataTo(StringStream* stream) const {
left()->PrintNameTo(stream);
stream->Add(" ");
right()->PrintNameTo(stream);
stream->Add(" ");
context()->PrintNameTo(stream);
}
Range* HValue::InferRange() {
if (representation().IsTagged()) {
// Tagged values are always in int32 range when converted to integer,
......
......@@ -1176,25 +1176,35 @@ class HCallConstantFunction: public HCall {
};
// TODO(3190496): This class uses hacks to get additional operands that ar
// not arguments to work with the current setup. This _needs_ a cleanup.
// (see HCall).
class HCallKeyed: public HCall {
public:
HCallKeyed(HValue* key, int argument_count)
: HCall(argument_count + 1) {
HCallKeyed(HValue* context, HValue* key, int argument_count)
: HCall(argument_count + 1), context_(NULL) {
SetOperandAt(0, key);
SetOperandAt(argument_count + 1, context);
}
virtual Representation RequiredInputRepresentation(int index) const {
return Representation::Tagged();
}
// TODO(3190496): This is a hack to get an additional operand that
// is not an argument to work with the current setup. This _needs_ a cleanup.
// (see HCall)
virtual void PrintDataTo(StringStream* stream) const;
HValue* key() const { return OperandAt(0); }
HValue* context() const { return context_; }
virtual int argument_count() const { return arguments_.length() - 1; }
virtual int OperandCount() const { return arguments_.length(); }
virtual HValue* OperandAt(int index) const { return arguments_[index]; }
virtual int OperandCount() const { return arguments_.length() + 1; }
virtual HValue* OperandAt(int index) const {
// The key and all the arguments are stored in the base class's
// arguments_ vector. The context is in the object itself. Ugly.
return (index <= argument_count()) ? arguments_[index] : context_;
}
virtual HPushArgument* PushArgumentAt(int index) const {
return HPushArgument::cast(OperandAt(index + 1));
}
......@@ -1203,44 +1213,100 @@ class HCallKeyed: public HCall {
}
DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call_keyed")
protected:
virtual void InternalSetOperandAt(int index, HValue* value);
private:
HValue* context_;
};
class HCallNamed: public HCall {
public:
HCallNamed(Handle<String> name, int argument_count)
: HCall(argument_count), name_(name) { }
HCallNamed(HValue* context, Handle<String> name, int argument_count)
: HCall(argument_count), context_(NULL), name_(name) {
SetOperandAt(argument_count, context);
}
virtual void PrintDataTo(StringStream* stream) const;
HValue* context() const { return context_; }
Handle<String> name() const { return name_; }
virtual int OperandCount() const { return arguments_.length() + 1; }
virtual HValue* OperandAt(int index) const {
// The arguments are in the base class's arguments_ vector. The context
// is in the object itself.
return (index < argument_count()) ? arguments_[index] : context_;
}
DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call_named")
protected:
virtual void InternalSetOperandAt(int index, HValue* value);
private:
HValue* context_;
Handle<String> name_;
};
class HCallFunction: public HCall {
public:
explicit HCallFunction(int argument_count) : HCall(argument_count) { }
HCallFunction(HValue* context, int argument_count)
: HCall(argument_count), context_(NULL) {
SetOperandAt(argument_count, context);
}
HValue* context() const { return context_; }
virtual int OperandCount() const { return arguments_.length() + 1; }
virtual HValue* OperandAt(int index) const {
// The arguments are in the base class's arguments_ vector. The context
// is in the object itself.
return (index < argument_count()) ? arguments_[index] : context_;
}
DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call_function")
protected:
virtual void InternalSetOperandAt(int index, HValue* value);
private:
HValue* context_;
};
class HCallGlobal: public HCall {
public:
HCallGlobal(Handle<String> name, int argument_count)
: HCall(argument_count), name_(name) { }
HCallGlobal(HValue* context, Handle<String> name, int argument_count)
: HCall(argument_count), context_(NULL), name_(name) {
SetOperandAt(argument_count, context);
}
virtual void PrintDataTo(StringStream* stream) const;
HValue* context() const { return context_; }
Handle<String> name() const { return name_; }
virtual int OperandCount() const { return arguments_.length() + 1; }
virtual HValue* OperandAt(int index) const {
// The arguments are in the base class's arguments_ vector. The context
// is in the object itself.
return (index < argument_count()) ? arguments_[index] : context_;
}
DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call_global")
protected:
virtual void InternalSetOperandAt(int index, HValue* value);
private:
HValue* context_;
Handle<String> name_;
};
......@@ -1262,15 +1328,33 @@ class HCallKnownGlobal: public HCall {
class HCallNew: public HCall {
public:
explicit HCallNew(int argument_count) : HCall(argument_count) { }
HCallNew(HValue* context, int argument_count)
: HCall(argument_count), context_(NULL) {
SetOperandAt(argument_count, context);
}
virtual Representation RequiredInputRepresentation(int index) const {
return Representation::Tagged();
}
HValue* context() const { return context_; }
HValue* constructor() const { return ArgumentAt(0); }
virtual int OperandCount() const { return arguments_.length() + 1; }
virtual HValue* OperandAt(int index) const {
// The arguments are in the base class's arguments_ vector. The context
// is in the object itself.
return (index < argument_count()) ? arguments_[index] : context_;
}
DECLARE_CONCRETE_INSTRUCTION(CallNew, "call_new")
protected:
virtual void InternalSetOperandAt(int index, HValue* value);
private:
HValue* context_;
};
......@@ -1861,7 +1945,6 @@ class HBinaryOperation: public HInstruction {
operands_[index] = value;
}
private:
HOperandVector<2> operands_;
};
......@@ -2278,20 +2361,40 @@ class HTypeofIs: public HUnaryPredicate {
};
class HInstanceOf: public HBinaryOperation {
class HInstanceOf: public HInstruction {
public:
HInstanceOf(HValue* left, HValue* right) : HBinaryOperation(left, right) {
HInstanceOf(HValue* context, HValue* left, HValue* right) {
SetOperandAt(0, context);
SetOperandAt(1, left);
SetOperandAt(2, right);
set_representation(Representation::Tagged());
SetAllSideEffects();
}
HValue* context() const { return operands_[0]; }
HValue* left() const { return operands_[1]; }
HValue* right() const { return operands_[2]; }
virtual bool EmitAtUses() const { return uses()->length() <= 1; }
virtual Representation RequiredInputRepresentation(int index) const {
return Representation::Tagged();
}
virtual void PrintDataTo(StringStream* stream) const;
virtual int OperandCount() const { return 3; }
virtual HValue* OperandAt(int index) const { return operands_[index]; }
DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance_of")
protected:
virtual void InternalSetOperandAt(int index, HValue* value) {
operands_[index] = value;
}
private:
HOperandVector<3> operands_;
};
......@@ -2560,10 +2663,11 @@ class HParameter: public HInstruction {
};
class HCallStub: public HInstruction {
class HCallStub: public HUnaryOperation {
public:
HCallStub(CodeStub::Major major_key, int argument_count)
: major_key_(major_key),
HCallStub(HValue* context, CodeStub::Major major_key, int argument_count)
: HUnaryOperation(context),
major_key_(major_key),
argument_count_(argument_count),
transcendental_type_(TranscendentalCache::kNumberOfCaches) {
set_representation(Representation::Tagged());
......@@ -2572,6 +2676,7 @@ class HCallStub: public HInstruction {
CodeStub::Major major_key() { return major_key_; }
int argument_count() { return argument_count_; }
HValue* context() { return OperandAt(0); }
void set_transcendental_type(TranscendentalCache::Type transcendental_type) {
transcendental_type_ = transcendental_type;
......@@ -2763,15 +2868,16 @@ class HLoadNamedField: public HUnaryOperation {
};
class HLoadNamedGeneric: public HUnaryOperation {
class HLoadNamedGeneric: public HBinaryOperation {
public:
HLoadNamedGeneric(HValue* object, Handle<Object> name)
: HUnaryOperation(object), name_(name) {
HLoadNamedGeneric(HValue* context, HValue* object, Handle<Object> name)
: HBinaryOperation(context, object), name_(name) {
set_representation(Representation::Tagged());
SetAllSideEffects();
}
HValue* object() const { return OperandAt(0); }
HValue* context() const { return OperandAt(0); }
HValue* object() const { return OperandAt(1); }
Handle<Object> name() const { return name_; }
virtual Representation RequiredInputRepresentation(int index) const {
......@@ -2848,17 +2954,34 @@ class HLoadKeyedFastElement: public HLoadKeyed {
class HLoadKeyedGeneric: public HLoadKeyed {
public:
HLoadKeyedGeneric(HValue* obj, HValue* key) : HLoadKeyed(obj, key) {
HLoadKeyedGeneric(HContext* context, HValue* obj, HValue* key)
: HLoadKeyed(obj, key), context_(NULL) {
SetOperandAt(2, context);
SetAllSideEffects();
}
HValue* context() const { return context_; }
HValue* object() const { return operands_[0]; }
HValue* key() const { return operands_[1]; }
virtual int OperandCount() const { return 3; }
virtual HValue* OperandAt(int index) const {
return (index < 2) ? operands_[index] : context_;
}
DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load_keyed_generic")
protected:
virtual void InternalSetOperandAt(int index, HValue* value);
private:
HValue* context_;
};
class HStoreNamed: public HBinaryOperation {
public:
HStoreNamed(HValue* obj, Handle<Object> name, HValue* val)
HStoreNamed(HValue* obj, Handle<String> name, HValue* val)
: HBinaryOperation(obj, val), name_(name) {
}
......@@ -2869,21 +2992,21 @@ class HStoreNamed: public HBinaryOperation {
virtual void PrintDataTo(StringStream* stream) const;
HValue* object() const { return OperandAt(0); }
Handle<Object> name() const { return name_; }
Handle<String> name() const { return name_; }
HValue* value() const { return OperandAt(1); }
void set_value(HValue* value) { SetOperandAt(1, value); }
DECLARE_INSTRUCTION(StoreNamed)
private:
Handle<Object> name_;
Handle<String> name_;
};
class HStoreNamedField: public HStoreNamed {
public:
HStoreNamedField(HValue* obj,
Handle<Object> name,
Handle<String> name,
HValue* val,
bool in_object,
int offset)
......@@ -2922,12 +3045,32 @@ class HStoreNamedField: public HStoreNamed {
class HStoreNamedGeneric: public HStoreNamed {
public:
HStoreNamedGeneric(HValue* obj, Handle<Object> name, HValue* val)
: HStoreNamed(obj, name, val) {
HStoreNamedGeneric(HValue* context,
HValue* object,
Handle<String> name,
HValue* value)
: HStoreNamed(object, name, value), context_(NULL) {
SetOperandAt(2, context);
SetAllSideEffects();
}
HValue* context() const { return context_; }
HValue* object() const { return operands_[0]; }
HValue* value() const { return operands_[1]; }
virtual int OperandCount() const { return 3; }
virtual HValue* OperandAt(int index) const {
return (index < 2) ? operands_[index] : context_;
}
DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store_named_generic")
protected:
virtual void InternalSetOperandAt(int index, HValue* value);
private:
HValue* context_;
};
......@@ -2962,7 +3105,6 @@ class HStoreKeyed: public HInstruction {
operands_[index] = value;
}
private:
HOperandVector<3> operands_;
};
......@@ -2987,12 +3129,33 @@ class HStoreKeyedFastElement: public HStoreKeyed {
class HStoreKeyedGeneric: public HStoreKeyed {
public:
HStoreKeyedGeneric(HValue* obj, HValue* key, HValue* val)
: HStoreKeyed(obj, key, val) {
HStoreKeyedGeneric(HValue* context,
HValue* object,
HValue* key,
HValue* value)
: HStoreKeyed(object, key, value), context_(NULL) {
SetOperandAt(3, context);
SetAllSideEffects();
}
HValue* context() const { return context_; }
HValue* object() const { return operands_[0]; }
HValue* key() const { return operands_[1]; }
HValue* value() const { return operands_[2]; }
virtual int OperandCount() const { return 4; }
virtual HValue* OperandAt(int index) const {
return (index < 3) ? operands_[index] : context_;
}
DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store_keyed_generic")
protected:
virtual void InternalSetOperandAt(int index, HValue* value);
private:
HValue* context_;
};
......@@ -3094,22 +3257,36 @@ class HArrayLiteral: public HMaterializedLiteral {
class HObjectLiteral: public HMaterializedLiteral {
public:
HObjectLiteral(Handle<FixedArray> constant_properties,
HObjectLiteral(HValue* context,
Handle<FixedArray> constant_properties,
bool fast_elements,
int literal_index,
int depth)
: HMaterializedLiteral(literal_index, depth),
context_(NULL),
constant_properties_(constant_properties),
fast_elements_(fast_elements) {}
fast_elements_(fast_elements) {
SetOperandAt(0, context);
}
HValue* context() const { return context_; }
Handle<FixedArray> constant_properties() const {
return constant_properties_;
}
bool fast_elements() const { return fast_elements_; }
virtual int OperandCount() const { return 1; }
virtual HValue* OperandAt(int index) const { return context_; }
DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral, "object_literal")
protected:
virtual void InternalSetOperandAt(int index, HValue* value) {
context_ = value;
}
private:
HValue* context_;
Handle<FixedArray> constant_properties_;
bool fast_elements_;
};
......
......@@ -3022,7 +3022,10 @@ void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
HObjectLiteral* literal = (new HObjectLiteral(expr->constant_properties(),
HContext* context = new HContext;
AddInstruction(context);
HObjectLiteral* literal = (new HObjectLiteral(context,
expr->constant_properties(),
expr->fast_elements(),
expr->literal_index(),
expr->depth()));
......@@ -3049,7 +3052,9 @@ void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
VISIT_FOR_VALUE(value);
HValue* value = Pop();
Handle<String> name = Handle<String>::cast(key->handle());
AddInstruction(new HStoreNamedGeneric(literal, name, value));
HStoreNamedGeneric* store =
new HStoreNamedGeneric(context, literal, name, value);
AddInstruction(store);
AddSimulate(key->id());
} else {
VISIT_FOR_EFFECT(value);
......@@ -3229,7 +3234,9 @@ HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object,
HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object,
Handle<String> name,
HValue* value) {
return new HStoreNamedGeneric(object, name, value);
HContext* context = new HContext;
AddInstruction(context);
return new HStoreNamedGeneric(context, object, name, value);
}
......@@ -3291,7 +3298,7 @@ void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
// If none of the properties were named fields we generate a
// generic store.
if (maps.length() == 0) {
HInstruction* instr = new HStoreNamedGeneric(object, name, value);
HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
Push(value);
instr->set_position(expr->position());
AddInstruction(instr);
......@@ -3305,7 +3312,7 @@ void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
subgraph->FinishExit(new HDeoptimize());
} else {
HInstruction* instr = new HStoreNamedGeneric(object, name, value);
HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
Push(value);
instr->set_position(expr->position());
AddInstruction(instr);
......@@ -3355,7 +3362,7 @@ void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
return;
} else {
instr = new HStoreNamedGeneric(object, name, value);
instr = BuildStoreNamedGeneric(object, name, value);
}
} else {
......@@ -3475,7 +3482,6 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
bool is_fast_elements = prop->IsMonomorphic() &&
prop->GetMonomorphicReceiverType()->has_fast_elements();
HInstruction* load = is_fast_elements
? BuildLoadKeyedFastElement(obj, key, prop)
: BuildLoadKeyedGeneric(obj, key);
......@@ -3678,7 +3684,9 @@ HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj,
Property* expr) {
ASSERT(expr->key()->IsPropertyName());
Handle<Object> name = expr->key()->AsLiteral()->handle();
return new HLoadNamedGeneric(obj, name);
HContext* context = new HContext;
AddInstruction(context);
return new HLoadNamedGeneric(context, obj, name);
}
......@@ -3707,7 +3715,9 @@ HInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj,
HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
HValue* key) {
return new HLoadKeyedGeneric(object, key);
HContext* context = new HContext;
AddInstruction(context);
return new HLoadKeyedGeneric(context, object, key);
}
......@@ -3738,7 +3748,9 @@ HInstruction* HGraphBuilder::BuildLoadKeyedFastElement(HValue* object,
HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object,
HValue* key,
HValue* value) {
return new HStoreKeyedGeneric(object, key, value);
HContext* context = new HContext;
AddInstruction(context);
return new HStoreKeyedGeneric(context, object, key, value);
}
......@@ -3917,7 +3929,9 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
// If we couldn't compute the target for any of the maps just perform an
// IC call.
if (maps.length() == 0) {
HCall* call = new HCallNamed(name, argument_count);
HContext* context = new HContext;
AddInstruction(context);
HCall* call = new HCallNamed(context, name, argument_count);
call->set_position(expr->position());
ProcessCall(call);
ast_context()->ReturnInstruction(call, expr->id());
......@@ -3929,7 +3943,9 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
subgraph->FinishExit(new HDeoptimize());
} else {
HCall* call = new HCallNamed(name, argument_count);
HContext* context = new HContext;
AddInstruction(context);
HCall* call = new HCallNamed(context, name, argument_count);
call->set_position(expr->position());
ProcessCall(call);
PushAndAdd(call);
......@@ -4349,7 +4365,9 @@ void HGraphBuilder::VisitCall(Call* expr) {
VisitArgumentList(expr->arguments());
CHECK_BAILOUT;
call = new HCallKeyed(key, argument_count);
HContext* context = new HContext;
AddInstruction(context);
call = new HCallKeyed(context, key, argument_count);
call->set_position(expr->position());
ProcessCall(call);
Drop(1); // Key.
......@@ -4388,7 +4406,9 @@ void HGraphBuilder::VisitCall(Call* expr) {
// When the target has a custom call IC generator, use the IC,
// because it is likely to generate better code. Also use the
// IC when a primitive receiver check is required.
call = new HCallNamed(name, argument_count);
HContext* context = new HContext;
AddInstruction(context);
call = new HCallNamed(context, name, argument_count);
} else {
AddCheckConstantFunction(expr, receiver, receiver_map, true);
......@@ -4417,7 +4437,9 @@ void HGraphBuilder::VisitCall(Call* expr) {
return;
} else {
call = new HCallNamed(name, argument_count);
HContext* context = new HContext;
AddInstruction(context);
call = new HCallNamed(context, name, argument_count);
}
} else {
......@@ -4487,7 +4509,7 @@ void HGraphBuilder::VisitCall(Call* expr) {
VisitArgumentList(expr->arguments());
CHECK_BAILOUT;
call = new HCallGlobal(var->name(), argument_count);
call = new HCallGlobal(context, var->name(), argument_count);
}
} else {
......@@ -4499,7 +4521,7 @@ void HGraphBuilder::VisitCall(Call* expr) {
VisitArgumentList(expr->arguments());
CHECK_BAILOUT;
call = new HCallFunction(argument_count);
call = new HCallFunction(context, argument_count);
}
}
......@@ -4518,7 +4540,9 @@ void HGraphBuilder::VisitCallNew(CallNew* expr) {
CHECK_BAILOUT;
int argument_count = expr->arguments()->length() + 1; // Plus constructor.
HCall* call = new HCallNew(argument_count);
HContext* context = new HContext;
AddInstruction(context);
HCall* call = new HCallNew(context, argument_count);
call->set_position(expr->position());
ProcessCall(call);
ast_context()->ReturnInstruction(call, expr->id());
......@@ -4786,7 +4810,7 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
HInstruction* store = is_fast_elements
? BuildStoreKeyedFastElement(obj, key, after, prop)
: new HStoreKeyedGeneric(obj, key, after);
: BuildStoreKeyedGeneric(obj, key, after);
AddInstruction(store);
// Drop the key from the bailout environment. Overwrite the receiver
......@@ -5043,7 +5067,9 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
// If the target is not null we have found a known global function that is
// assumed to stay the same for this instanceof.
if (target.is_null()) {
instr = new HInstanceOf(left, right);
HContext* context = new HContext;
AddInstruction(context);
instr = new HInstanceOf(context, left, right);
} else {
AddInstruction(new HCheckFunction(right, target));
instr = new HInstanceOfKnownGlobal(left, target);
......@@ -5254,7 +5280,10 @@ void HGraphBuilder::GenerateStringCharFromCode(int argument_count,
void HGraphBuilder::GenerateStringCharAt(int argument_count, int ast_id) {
ASSERT_EQ(2, argument_count);
PushArgumentsForStubCall(argument_count);
HCallStub* result = new HCallStub(CodeStub::StringCharAt, argument_count);
HContext* context = new HContext;
AddInstruction(context);
HCallStub* result =
new HCallStub(context, CodeStub::StringCharAt, argument_count);
ast_context()->ReturnInstruction(result, ast_id);
}
......@@ -5284,7 +5313,10 @@ void HGraphBuilder::GenerateRandomHeapNumber(int argument_count, int ast_id) {
void HGraphBuilder::GenerateStringAdd(int argument_count, int ast_id) {
ASSERT_EQ(2, argument_count);
PushArgumentsForStubCall(argument_count);
HCallStub* result = new HCallStub(CodeStub::StringAdd, argument_count);
HContext* context = new HContext;
AddInstruction(context);
HCallStub* result =
new HCallStub(context, CodeStub::StringAdd, argument_count);
ast_context()->ReturnInstruction(result, ast_id);
}
......@@ -5293,7 +5325,10 @@ void HGraphBuilder::GenerateStringAdd(int argument_count, int ast_id) {
void HGraphBuilder::GenerateSubString(int argument_count, int ast_id) {
ASSERT_EQ(3, argument_count);
PushArgumentsForStubCall(argument_count);
HCallStub* result = new HCallStub(CodeStub::SubString, argument_count);
HContext* context = new HContext;
AddInstruction(context);
HCallStub* result =
new HCallStub(context, CodeStub::SubString, argument_count);
ast_context()->ReturnInstruction(result, ast_id);
}
......@@ -5302,7 +5337,10 @@ void HGraphBuilder::GenerateSubString(int argument_count, int ast_id) {
void HGraphBuilder::GenerateStringCompare(int argument_count, int ast_id) {
ASSERT_EQ(2, argument_count);
PushArgumentsForStubCall(argument_count);
HCallStub* result = new HCallStub(CodeStub::StringCompare, argument_count);
HContext* context = new HContext;
AddInstruction(context);
HCallStub* result =
new HCallStub(context, CodeStub::StringCompare, argument_count);
ast_context()->ReturnInstruction(result, ast_id);
}
......@@ -5311,7 +5349,10 @@ void HGraphBuilder::GenerateStringCompare(int argument_count, int ast_id) {
void HGraphBuilder::GenerateRegExpExec(int argument_count, int ast_id) {
ASSERT_EQ(4, argument_count);
PushArgumentsForStubCall(argument_count);
HCallStub* result = new HCallStub(CodeStub::RegExpExec, argument_count);
HContext* context = new HContext;
AddInstruction(context);
HCallStub* result =
new HCallStub(context, CodeStub::RegExpExec, argument_count);
ast_context()->ReturnInstruction(result, ast_id);
}
......@@ -5321,8 +5362,10 @@ void HGraphBuilder::GenerateRegExpConstructResult(int argument_count,
int ast_id) {
ASSERT_EQ(3, argument_count);
PushArgumentsForStubCall(argument_count);
HContext* context = new HContext;
AddInstruction(context);
HCallStub* result =
new HCallStub(CodeStub::RegExpConstructResult, argument_count);
new HCallStub(context,CodeStub::RegExpConstructResult, argument_count);
ast_context()->ReturnInstruction(result, ast_id);
}
......@@ -5337,7 +5380,10 @@ void HGraphBuilder::GenerateGetFromCache(int argument_count, int ast_id) {
void HGraphBuilder::GenerateNumberToString(int argument_count, int ast_id) {
ASSERT_EQ(1, argument_count);
PushArgumentsForStubCall(argument_count);
HCallStub* result = new HCallStub(CodeStub::NumberToString, argument_count);
HContext* context = new HContext;
AddInstruction(context);
HCallStub* result =
new HCallStub(context, CodeStub::NumberToString, argument_count);
ast_context()->ReturnInstruction(result, ast_id);
}
......@@ -5369,8 +5415,10 @@ void HGraphBuilder::GenerateMathPow(int argument_count, int ast_id) {
void HGraphBuilder::GenerateMathSin(int argument_count, int ast_id) {
ASSERT_EQ(1, argument_count);
PushArgumentsForStubCall(argument_count);
HContext* context = new HContext;
AddInstruction(context);
HCallStub* result =
new HCallStub(CodeStub::TranscendentalCache, argument_count);
new HCallStub(context, CodeStub::TranscendentalCache, argument_count);
result->set_transcendental_type(TranscendentalCache::SIN);
ast_context()->ReturnInstruction(result, ast_id);
}
......@@ -5379,8 +5427,10 @@ void HGraphBuilder::GenerateMathSin(int argument_count, int ast_id) {
void HGraphBuilder::GenerateMathCos(int argument_count, int ast_id) {
ASSERT_EQ(1, argument_count);
PushArgumentsForStubCall(argument_count);
HContext* context = new HContext;
AddInstruction(context);
HCallStub* result =
new HCallStub(CodeStub::TranscendentalCache, argument_count);
new HCallStub(context, CodeStub::TranscendentalCache, argument_count);
result->set_transcendental_type(TranscendentalCache::COS);
ast_context()->ReturnInstruction(result, ast_id);
}
......@@ -5389,8 +5439,10 @@ void HGraphBuilder::GenerateMathCos(int argument_count, int ast_id) {
void HGraphBuilder::GenerateMathLog(int argument_count, int ast_id) {
ASSERT_EQ(1, argument_count);
PushArgumentsForStubCall(argument_count);
HContext* context = new HContext;
AddInstruction(context);
HCallStub* result =
new HCallStub(CodeStub::TranscendentalCache, argument_count);
new HCallStub(context, CodeStub::TranscendentalCache, argument_count);
result->set_transcendental_type(TranscendentalCache::LOG);
ast_context()->ReturnInstruction(result, ast_id);
}
......
......@@ -30,7 +30,7 @@
// The original source code covered by the above license above has been
// modified significantly by Google Inc.
// Copyright 2010 the V8 project authors. All rights reserved.
// Copyright 2011 the V8 project authors. All rights reserved.
// A light-weight IA32 Assembler.
......@@ -64,30 +64,14 @@ namespace internal {
// and best performance in optimized code.
//
struct Register {
static const int kNumAllocatableRegisters = 5;
static const int kNumAllocatableRegisters = 6;
static const int kNumRegisters = 8;
static int ToAllocationIndex(Register reg) {
ASSERT(reg.code() < 4 || reg.code() == 7);
return (reg.code() == 7) ? 4 : reg.code();
}
static inline const char* AllocationIndexToString(int index);
static Register FromAllocationIndex(int index) {
ASSERT(index >= 0 && index < kNumAllocatableRegisters);
return (index == 4) ? from_code(7) : from_code(index);
}
static inline int ToAllocationIndex(Register reg);
static const char* AllocationIndexToString(int index) {
ASSERT(index >= 0 && index < kNumAllocatableRegisters);
const char* const names[] = {
"eax",
"ecx",
"edx",
"ebx",
"edi"
};
return names[index];
}
static inline Register FromAllocationIndex(int index);
static Register from_code(int code) {
Register r = { code };
......@@ -110,6 +94,7 @@ struct Register {
int code_;
};
const Register eax = { 0 };
const Register ecx = { 1 };
const Register edx = { 2 };
......@@ -121,6 +106,26 @@ const Register edi = { 7 };
const Register no_reg = { -1 };
inline const char* Register::AllocationIndexToString(int index) {
ASSERT(index >= 0 && index < kNumAllocatableRegisters);
// This is the mapping of allocation indices to registers.
const char* const kNames[] = { "eax", "ecx", "edx", "ebx", "esi", "edi" };
return kNames[index];
}
inline int Register::ToAllocationIndex(Register reg) {
ASSERT(reg.is_valid() && !reg.is(esp) && !reg.is(ebp));
return (reg.code() >= 6) ? reg.code() - 2 : reg.code();
}
inline Register Register::FromAllocationIndex(int index) {
ASSERT(index >= 0 && index < kNumAllocatableRegisters);
return (index >= 4) ? from_code(index + 2) : from_code(index);
}
struct XMMRegister {
static const int kNumAllocatableRegisters = 7;
static const int kNumRegisters = 8;
......
......@@ -615,6 +615,7 @@ void FullCodeGenerator::Move(Slot* dst,
// Emit the write barrier code if the location is in the heap.
if (dst->type() == Slot::CONTEXT) {
int offset = Context::SlotOffset(dst->index());
ASSERT(!scratch1.is(esi) && !src.is(esi) && !scratch2.is(esi));
__ RecordWrite(scratch1, offset, src, scratch2);
}
}
......
......@@ -157,6 +157,8 @@ bool LCodeGen::GeneratePrologue() {
// Trace the call.
if (FLAG_trace) {
// We have not executed any compiled code yet, so esi still holds the
// incoming context.
__ CallRuntime(Runtime::kTraceEnter, 0);
}
return !is_aborted();
......@@ -367,10 +369,14 @@ void LCodeGen::AddToTranslation(Translation* translation,
void LCodeGen::CallCode(Handle<Code> code,
RelocInfo::Mode mode,
LInstruction* instr) {
LInstruction* instr,
bool adjusted) {
ASSERT(instr != NULL);
LPointerMap* pointers = instr->pointer_map();
RecordPosition(pointers->position());
if (!adjusted) {
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
}
__ call(code, mode);
RegisterLazyDeoptimization(instr);
......@@ -383,15 +389,19 @@ void LCodeGen::CallCode(Handle<Code> code,
}
void LCodeGen::CallRuntime(Runtime::Function* function,
int num_arguments,
LInstruction* instr) {
void LCodeGen::CallRuntime(Runtime::Function* fun,
int argc,
LInstruction* instr,
bool adjusted) {
ASSERT(instr != NULL);
ASSERT(instr->HasPointerMap());
LPointerMap* pointers = instr->pointer_map();
RecordPosition(pointers->position());
__ CallRuntime(function, num_arguments);
if (!adjusted) {
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
}
__ CallRuntime(fun, argc);
RegisterLazyDeoptimization(instr);
}
......@@ -568,10 +578,6 @@ void LCodeGen::RecordSafepoint(
safepoint.DefinePointerRegister(ToRegister(pointer));
}
}
if (kind & Safepoint::kWithRegisters) {
// Register esi always contains a pointer to the context.
safepoint.DefinePointerRegister(esi);
}
}
......@@ -635,6 +641,7 @@ void LCodeGen::DoParameter(LParameter* instr) {
void LCodeGen::DoCallStub(LCallStub* instr) {
ASSERT(ToRegister(instr->context()).is(esi));
ASSERT(ToRegister(instr->result()).is(eax));
switch (instr->hydrogen()->major_key()) {
case CodeStub::RegExpConstructResult: {
......@@ -1023,7 +1030,7 @@ void LCodeGen::DoBitNotI(LBitNotI* instr) {
void LCodeGen::DoThrow(LThrow* instr) {
__ push(ToOperand(instr->InputAt(0)));
CallRuntime(Runtime::kThrow, 1, instr);
CallRuntime(Runtime::kThrow, 1, instr, false);
if (FLAG_debug_code) {
Comment("Unreachable code.");
......@@ -1095,7 +1102,7 @@ void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
ASSERT(ToRegister(instr->result()).is(eax));
TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false);
}
......@@ -1208,6 +1215,7 @@ void LCodeGen::EmitGoto(int block, LDeferredCode* deferred_stack_check) {
void LCodeGen::DoDeferredStackCheck(LGoto* instr) {
__ pushad();
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ CallRuntimeSaveDoubles(Runtime::kStackGuard);
RecordSafepointWithRegisters(
instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
......@@ -1698,6 +1706,7 @@ void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
// Object and function are in fixed registers defined by the stub.
ASSERT(ToRegister(instr->context()).is(esi));
InstanceofStub stub(InstanceofStub::kArgsInRegisters);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
......@@ -1713,6 +1722,7 @@ void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) {
ASSERT(ToRegister(instr->context()).is(esi));
int true_block = chunk_->LookupDestination(instr->true_block_id());
int false_block = chunk_->LookupDestination(instr->false_block_id());
......@@ -1806,12 +1816,13 @@ void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
Register temp = ToRegister(instr->TempAt(0));
ASSERT(temp.is(edi));
__ mov(InstanceofStub::right(), Immediate(instr->function()));
static const int kAdditionalDelta = 13;
static const int kAdditionalDelta = 16;
int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta;
Label before_push_delta;
__ bind(&before_push_delta);
__ mov(temp, Immediate(delta));
__ mov(Operand(esp, EspIndexForPushAll(temp) * kPointerSize), temp);
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ call(stub.GetCode(), RelocInfo::CODE_TARGET);
ASSERT_EQ(kAdditionalDelta,
masm_->SizeOfCodeGeneratedSince(&before_push_delta));
......@@ -1848,7 +1859,7 @@ void LCodeGen::DoCmpT(LCmpT* instr) {
Token::Value op = instr->op();
Handle<Code> ic = CompareIC::GetUninitialized(op);
CallCode(ic, RelocInfo::CODE_TARGET, instr);
CallCode(ic, RelocInfo::CODE_TARGET, instr, false);
Condition condition = ComputeCompareCondition(op);
if (op == Token::GT || op == Token::LTE) {
......@@ -1871,7 +1882,7 @@ void LCodeGen::DoCmpTAndBranch(LCmpTAndBranch* instr) {
int false_block = chunk_->LookupDestination(instr->false_block_id());
Handle<Code> ic = CompareIC::GetUninitialized(op);
CallCode(ic, RelocInfo::CODE_TARGET, instr);
CallCode(ic, RelocInfo::CODE_TARGET, instr, false);
// The compare stub expects compare condition and the input operands
// reversed for GT and LTE.
......@@ -1886,9 +1897,12 @@ void LCodeGen::DoCmpTAndBranch(LCmpTAndBranch* instr) {
void LCodeGen::DoReturn(LReturn* instr) {
if (FLAG_trace) {
// Preserve the return value on the stack and rely on the runtime
// call to return the value in the same register.
// Preserve the return value on the stack and rely on the runtime call
// to return the value in the same register. We're leaving the code
// managed by the register allocator and tearing down the frame, it's
// safe to write to the context register.
__ push(eax);
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kTraceExit, 1);
}
__ mov(esp, ebp);
......@@ -1957,6 +1971,7 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
ASSERT(ToRegister(instr->context()).is(esi));
ASSERT(ToRegister(instr->object()).is(eax));
ASSERT(ToRegister(instr->result()).is(eax));
......@@ -2059,6 +2074,7 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
ASSERT(ToRegister(instr->context()).is(esi));
ASSERT(ToRegister(instr->object()).is(edx));
ASSERT(ToRegister(instr->key()).is(eax));
......@@ -2138,7 +2154,11 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
__ jmp(&receiver_ok);
__ bind(&global_receiver);
__ mov(receiver, GlobalObjectOperand());
// TODO(kmillikin): We have a hydrogen value for the global object. See
// if it's better to use it than to explicitly fetch it from the context
// here.
__ mov(receiver, Operand(ebp, StandardFrameConstants::kContextOffset));
__ mov(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX));
__ bind(&receiver_ok);
Label invoke;
......@@ -2176,9 +2196,6 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
ASSERT(receiver.is(eax));
v8::internal::ParameterCount actual(eax);
__ InvokeFunction(edi, actual, CALL_FUNCTION, &safepoint_generator);
// Restore context.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
}
......@@ -2194,7 +2211,7 @@ void LCodeGen::DoPushArgument(LPushArgument* instr) {
void LCodeGen::DoContext(LContext* instr) {
Register result = ToRegister(instr->result());
__ mov(result, esi);
__ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset));
}
......@@ -2230,6 +2247,8 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
(scope()->num_heap_slots() > 0);
if (change_context) {
__ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
} else {
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
}
// Set eax to arguments count if adaption is not needed. Assumes that eax
......@@ -2250,9 +2269,6 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
// Setup deoptimization.
RegisterLazyDeoptimization(instr);
// Restore context.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
}
......@@ -2295,6 +2311,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) {
// Slow case: Call the runtime system to do the number allocation.
__ bind(&slow);
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
RecordSafepointWithRegisters(
instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
......@@ -2506,7 +2523,7 @@ void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
TranscendentalCacheStub stub(TranscendentalCache::LOG,
TranscendentalCacheStub::UNTAGGED);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false);
}
......@@ -2514,7 +2531,7 @@ void LCodeGen::DoMathCos(LUnaryMathOperation* instr) {
ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
TranscendentalCacheStub stub(TranscendentalCache::COS,
TranscendentalCacheStub::UNTAGGED);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false);
}
......@@ -2522,7 +2539,7 @@ void LCodeGen::DoMathSin(LUnaryMathOperation* instr) {
ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
TranscendentalCacheStub stub(TranscendentalCache::SIN,
TranscendentalCacheStub::UNTAGGED);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false);
}
......@@ -2560,46 +2577,46 @@ void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
void LCodeGen::DoCallKeyed(LCallKeyed* instr) {
ASSERT(ToRegister(instr->context()).is(esi));
ASSERT(ToRegister(instr->key()).is(ecx));
ASSERT(ToRegister(instr->result()).is(eax));
ASSERT(ToRegister(instr->InputAt(0)).is(ecx));
int arity = instr->arity();
Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arity, NOT_IN_LOOP);
CallCode(ic, RelocInfo::CODE_TARGET, instr);
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
}
void LCodeGen::DoCallNamed(LCallNamed* instr) {
ASSERT(ToRegister(instr->context()).is(esi));
ASSERT(ToRegister(instr->result()).is(eax));
int arity = instr->arity();
Handle<Code> ic = StubCache::ComputeCallInitialize(arity, NOT_IN_LOOP);
__ mov(ecx, instr->name());
CallCode(ic, RelocInfo::CODE_TARGET, instr);
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
}
void LCodeGen::DoCallFunction(LCallFunction* instr) {
ASSERT(ToRegister(instr->context()).is(esi));
ASSERT(ToRegister(instr->result()).is(eax));
int arity = instr->arity();
CallFunctionStub stub(arity, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
__ Drop(1);
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
}
void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
ASSERT(ToRegister(instr->context()).is(esi));
ASSERT(ToRegister(instr->result()).is(eax));
int arity = instr->arity();
Handle<Code> ic = StubCache::ComputeCallInitialize(arity, NOT_IN_LOOP);
__ mov(ecx, instr->name());
CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr);
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
}
......@@ -2611,7 +2628,8 @@ void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
void LCodeGen::DoCallNew(LCallNew* instr) {
ASSERT(ToRegister(instr->InputAt(0)).is(edi));
ASSERT(ToRegister(instr->context()).is(esi));
ASSERT(ToRegister(instr->constructor()).is(edi));
ASSERT(ToRegister(instr->result()).is(eax));
Handle<Code> builtin(Builtins::builtin(Builtins::JSConstructCall));
......@@ -2621,7 +2639,7 @@ void LCodeGen::DoCallNew(LCallNew* instr) {
void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
CallRuntime(instr->function(), instr->arity(), instr);
CallRuntime(instr->function(), instr->arity(), instr, false);
}
......@@ -2656,6 +2674,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
ASSERT(ToRegister(instr->context()).is(esi));
ASSERT(ToRegister(instr->object()).is(edx));
ASSERT(ToRegister(instr->value()).is(eax));
......@@ -2704,6 +2723,7 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
ASSERT(ToRegister(instr->context()).is(esi));
ASSERT(ToRegister(instr->object()).is(edx));
ASSERT(ToRegister(instr->key()).is(ecx));
ASSERT(ToRegister(instr->value()).is(eax));
......@@ -2839,6 +2859,7 @@ void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
__ SmiTag(index);
__ push(index);
}
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ CallRuntimeSaveDoubles(Runtime::kStringCharCodeAt);
RecordSafepointWithRegisters(
instr->pointer_map(), 2, Safepoint::kNoDeoptimizationIndex);
......@@ -2916,6 +2937,7 @@ void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) {
// integer value.
__ mov(Operand(esp, EspIndexForPushAll(reg) * kPointerSize), Immediate(0));
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
RecordSafepointWithRegisters(
instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
......@@ -2963,6 +2985,7 @@ void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
__ Set(reg, Immediate(0));
__ PushSafepointRegisters();
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
RecordSafepointWithRegisters(
instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
......@@ -3378,21 +3401,22 @@ void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
FastCloneShallowArrayStub::Mode mode =
FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS;
FastCloneShallowArrayStub stub(mode, length);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false);
} else if (instr->hydrogen()->depth() > 1) {
CallRuntime(Runtime::kCreateArrayLiteral, 3, instr);
CallRuntime(Runtime::kCreateArrayLiteral, 3, instr, false);
} else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr);
CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr, false);
} else {
FastCloneShallowArrayStub::Mode mode =
FastCloneShallowArrayStub::CLONE_ELEMENTS;
FastCloneShallowArrayStub stub(mode, length);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false);
}
}
void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) {
ASSERT(ToRegister(instr->context()).is(esi));
// Setup the parameters to the stub/runtime call.
__ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
__ push(FieldOperand(eax, JSFunction::kLiteralsOffset));
......@@ -3430,7 +3454,7 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
__ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index())));
__ push(Immediate(instr->hydrogen()->pattern()));
__ push(Immediate(instr->hydrogen()->flags()));
CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr);
CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr, false);
__ mov(ebx, eax);
__ bind(&materialized);
......@@ -3442,7 +3466,7 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
__ bind(&runtime_allocate);
__ push(ebx);
__ push(Immediate(Smi::FromInt(size)));
CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
CallRuntime(Runtime::kAllocateInNewSpace, 1, instr, false);
__ pop(ebx);
__ bind(&allocated);
......@@ -3469,14 +3493,14 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
if (shared_info->num_literals() == 0 && !pretenure) {
FastNewClosureStub stub;
__ push(Immediate(shared_info));
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false);
} else {
__ push(esi);
__ push(Operand(ebp, StandardFrameConstants::kContextOffset));
__ push(Immediate(shared_info));
__ push(Immediate(pretenure
? Factory::true_value()
: Factory::false_value()));
CallRuntime(Runtime::kNewClosure, 3, instr);
CallRuntime(Runtime::kNewClosure, 3, instr, false);
}
}
......@@ -3488,7 +3512,7 @@ void LCodeGen::DoTypeof(LTypeof* instr) {
} else {
__ push(ToOperand(input));
}
CallRuntime(Runtime::kTypeof, 1, instr);
CallRuntime(Runtime::kTypeof, 1, instr, false);
}
......@@ -3682,6 +3706,7 @@ void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) {
SafepointGenerator safepoint_generator(this,
pointers,
env->deoptimization_index());
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, &safepoint_generator);
}
......@@ -3694,7 +3719,7 @@ void LCodeGen::DoStackCheck(LStackCheck* instr) {
__ j(above_equal, &done);
StackCheckStub stub;
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false);
__ bind(&done);
}
......
......@@ -149,17 +149,14 @@ class LCodeGen BASE_EMBEDDED {
bool GenerateDeferredCode();
bool GenerateSafepointTable();
void CallCode(Handle<Code> code,
RelocInfo::Mode mode,
LInstruction* instr);
void CallRuntime(Runtime::Function* function,
int num_arguments,
LInstruction* instr);
void CallRuntime(Runtime::FunctionId id,
int num_arguments,
LInstruction* instr) {
void CallCode(Handle<Code> code, RelocInfo::Mode mode, LInstruction* instr,
bool adjusted = true);
void CallRuntime(Runtime::Function* fun, int argc, LInstruction* instr,
bool adjusted = true);
void CallRuntime(Runtime::FunctionId id, int argc, LInstruction* instr,
bool adjusted = true) {
Runtime::Function* function = Runtime::FunctionForId(id);
CallRuntime(function, num_arguments, instr);
CallRuntime(function, argc, instr, adjusted);
}
// Generate a direct call to a known function. Expects the function
......
......@@ -1090,10 +1090,11 @@ LInstruction* LChunkBuilder::DoTest(HTest* instr) {
UseRegisterAtStart(compare->right()));
} else if (v->IsInstanceOf()) {
HInstanceOf* instance_of = HInstanceOf::cast(v);
LOperand* left = UseFixed(instance_of->left(), InstanceofStub::left());
LOperand* right = UseFixed(instance_of->right(), InstanceofStub::right());
LOperand* context = UseFixed(instance_of->context(), esi);
LInstanceOfAndBranch* result =
new LInstanceOfAndBranch(
UseFixed(instance_of->left(), InstanceofStub::left()),
UseFixed(instance_of->right(), InstanceofStub::right()));
new LInstanceOfAndBranch(context, left, right);
return MarkAsCall(result, instr);
} else if (v->IsTypeofIs()) {
HTypeofIs* typeof_is = HTypeofIs::cast(v);
......@@ -1134,9 +1135,10 @@ LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
LInstanceOf* result =
new LInstanceOf(UseFixed(instr->left(), InstanceofStub::left()),
UseFixed(instr->right(), InstanceofStub::right()));
LOperand* left = UseFixed(instr->left(), InstanceofStub::left());
LOperand* right = UseFixed(instr->right(), InstanceofStub::right());
LOperand* context = UseFixed(instr->context(), esi);
LInstanceOf* result = new LInstanceOf(context, left, right);
return MarkAsCall(DefineFixed(result, eax), instr);
}
......@@ -1234,21 +1236,27 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
ASSERT(instr->key()->representation().IsTagged());
argument_count_ -= instr->argument_count();
LOperand* context = UseFixed(instr->context(), esi);
LOperand* key = UseFixed(instr->key(), ecx);
return MarkAsCall(DefineFixed(new LCallKeyed(key), eax), instr);
argument_count_ -= instr->argument_count();
LCallKeyed* result = new LCallKeyed(context, key);
return MarkAsCall(DefineFixed(result, eax), instr);
}
LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
LOperand* context = UseFixed(instr->context(), esi);
argument_count_ -= instr->argument_count();
return MarkAsCall(DefineFixed(new LCallNamed, eax), instr);
LCallNamed* result = new LCallNamed(context);
return MarkAsCall(DefineFixed(result, eax), instr);
}
LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
LOperand* context = UseFixed(instr->context(), esi);
argument_count_ -= instr->argument_count();
return MarkAsCall(DefineFixed(new LCallGlobal, eax), instr);
LCallGlobal* result = new LCallGlobal(context);
return MarkAsCall(DefineFixed(result, eax), instr);
}
......@@ -1259,16 +1267,19 @@ LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
LOperand* context = UseFixed(instr->context(), esi);
LOperand* constructor = UseFixed(instr->constructor(), edi);
argument_count_ -= instr->argument_count();
LCallNew* result = new LCallNew(constructor);
LCallNew* result = new LCallNew(context, constructor);
return MarkAsCall(DefineFixed(result, eax), instr);
}
LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
LOperand* context = UseFixed(instr->context(), esi);
argument_count_ -= instr->argument_count();
return MarkAsCall(DefineFixed(new LCallFunction, eax), instr);
LCallFunction* result = new LCallFunction(context);
return MarkAsCall(DefineFixed(result, eax), instr);
}
......@@ -1737,8 +1748,9 @@ LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
LOperand* context = UseFixed(instr->context(), esi);
LOperand* object = UseFixed(instr->object(), eax);
LLoadNamedGeneric* result = new LLoadNamedGeneric(object);
LLoadNamedGeneric* result = new LLoadNamedGeneric(context, object);
return MarkAsCall(DefineFixed(result, eax), instr);
}
......@@ -1769,10 +1781,11 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
LOperand* context = UseFixed(instr->context(), esi);
LOperand* object = UseFixed(instr->object(), edx);
LOperand* key = UseFixed(instr->key(), eax);
LLoadKeyedGeneric* result = new LLoadKeyedGeneric(object, key);
LLoadKeyedGeneric* result = new LLoadKeyedGeneric(context, object, key);
return MarkAsCall(DefineFixed(result, eax), instr);
}
......@@ -1797,15 +1810,18 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
LOperand* obj = UseFixed(instr->object(), edx);
LOperand* context = UseFixed(instr->context(), esi);
LOperand* object = UseFixed(instr->object(), edx);
LOperand* key = UseFixed(instr->key(), ecx);
LOperand* val = UseFixed(instr->value(), eax);
LOperand* value = UseFixed(instr->value(), eax);
ASSERT(instr->object()->representation().IsTagged());
ASSERT(instr->key()->representation().IsTagged());
ASSERT(instr->value()->representation().IsTagged());
return MarkAsCall(new LStoreKeyedGeneric(obj, key, val), instr);
LStoreKeyedGeneric* result =
new LStoreKeyedGeneric(context, object, key, value);
return MarkAsCall(result, instr);
}
......@@ -1831,10 +1847,11 @@ LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
LOperand* obj = UseFixed(instr->object(), edx);
LOperand* val = UseFixed(instr->value(), eax);
LOperand* context = UseFixed(instr->context(), esi);
LOperand* object = UseFixed(instr->object(), edx);
LOperand* value = UseFixed(instr->value(), eax);
LStoreNamedGeneric* result = new LStoreNamedGeneric(obj, val);
LStoreNamedGeneric* result = new LStoreNamedGeneric(context, object, value);
return MarkAsCall(result, instr);
}
......@@ -1859,7 +1876,8 @@ LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) {
LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
return MarkAsCall(DefineFixed(new LObjectLiteral, eax), instr);
LOperand* context = UseFixed(instr->context(), esi);
return MarkAsCall(DefineFixed(new LObjectLiteral(context), eax), instr);
}
......@@ -1900,8 +1918,10 @@ LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
LOperand* context = UseFixed(instr->context(), esi);
argument_count_ -= instr->argument_count();
return MarkAsCall(DefineFixed(new LCallStub, eax), instr);
LCallStub* result = new LCallStub(context);
return MarkAsCall(DefineFixed(result, eax), instr);
}
......
......@@ -425,11 +425,17 @@ class LParameter: public LTemplateInstruction<1, 0, 0> {
};
class LCallStub: public LTemplateInstruction<1, 0, 0> {
class LCallStub: public LTemplateInstruction<1, 1, 0> {
public:
explicit LCallStub(LOperand* context) {
inputs_[0] = context;
}
DECLARE_CONCRETE_INSTRUCTION(CallStub, "call-stub")
DECLARE_HYDROGEN_ACCESSOR(CallStub)
LOperand* context() { return inputs_[0]; }
TranscendentalCache::Type transcendental_type() {
return hydrogen()->transcendental_type();
}
......@@ -834,25 +840,31 @@ class LCmpTAndBranch: public LControlInstruction<2, 0> {
};
class LInstanceOf: public LTemplateInstruction<1, 2, 0> {
class LInstanceOf: public LTemplateInstruction<1, 3, 0> {
public:
LInstanceOf(LOperand* left, LOperand* right) {
inputs_[0] = left;
inputs_[1] = right;
LInstanceOf(LOperand* context, LOperand* left, LOperand* right) {
inputs_[0] = context;
inputs_[1] = left;
inputs_[2] = right;
}
DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance-of")
LOperand* context() { return inputs_[0]; }
};
class LInstanceOfAndBranch: public LControlInstruction<2, 0> {
class LInstanceOfAndBranch: public LControlInstruction<3, 0> {
public:
LInstanceOfAndBranch(LOperand* left, LOperand* right) {
inputs_[0] = left;
inputs_[1] = right;
LInstanceOfAndBranch(LOperand* context, LOperand* left, LOperand* right) {
inputs_[0] = context;
inputs_[1] = left;
inputs_[2] = right;
}
DECLARE_CONCRETE_INSTRUCTION(InstanceOfAndBranch, "instance-of-and-branch")
LOperand* context() { return inputs_[0]; }
};
......@@ -1134,16 +1146,18 @@ class LLoadNamedField: public LTemplateInstruction<1, 1, 0> {
};
class LLoadNamedGeneric: public LTemplateInstruction<1, 1, 0> {
class LLoadNamedGeneric: public LTemplateInstruction<1, 2, 0> {
public:
explicit LLoadNamedGeneric(LOperand* object) {
inputs_[0] = object;
LLoadNamedGeneric(LOperand* context, LOperand* object) {
inputs_[0] = context;
inputs_[1] = object;
}
DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load-named-generic")
DECLARE_HYDROGEN_ACCESSOR(LoadNamedGeneric)
LOperand* object() { return inputs_[0]; }
LOperand* context() { return inputs_[0]; }
LOperand* object() { return inputs_[1]; }
Handle<Object> name() const { return hydrogen()->name(); }
};
......@@ -1187,17 +1201,19 @@ class LLoadKeyedFastElement: public LTemplateInstruction<1, 2, 0> {
};
class LLoadKeyedGeneric: public LTemplateInstruction<1, 2, 0> {
class LLoadKeyedGeneric: public LTemplateInstruction<1, 3, 0> {
public:
LLoadKeyedGeneric(LOperand* obj, LOperand* key) {
inputs_[0] = obj;
inputs_[1] = key;
LLoadKeyedGeneric(LOperand* context, LOperand* obj, LOperand* key) {
inputs_[0] = context;
inputs_[1] = obj;
inputs_[2] = key;
}
DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load-keyed-generic")
LOperand* object() { return inputs_[0]; }
LOperand* key() { return inputs_[1]; }
LOperand* context() { return inputs_[0]; }
LOperand* object() { return inputs_[1]; }
LOperand* key() { return inputs_[2]; }
};
......@@ -1319,49 +1335,68 @@ class LCallConstantFunction: public LTemplateInstruction<1, 0, 0> {
};
class LCallKeyed: public LTemplateInstruction<1, 1, 0> {
class LCallKeyed: public LTemplateInstruction<1, 2, 0> {
public:
explicit LCallKeyed(LOperand* key) {
inputs_[0] = key;
LCallKeyed(LOperand* context, LOperand* key) {
inputs_[0] = context;
inputs_[1] = key;
}
DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call-keyed")
DECLARE_HYDROGEN_ACCESSOR(CallKeyed)
LOperand* context() { return inputs_[0]; }
LOperand* key() { return inputs_[1]; }
virtual void PrintDataTo(StringStream* stream);
int arity() const { return hydrogen()->argument_count() - 1; }
};
class LCallNamed: public LTemplateInstruction<1, 0, 0> {
class LCallNamed: public LTemplateInstruction<1, 1, 0> {
public:
explicit LCallNamed(LOperand* context) {
inputs_[0] = context;
}
DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call-named")
DECLARE_HYDROGEN_ACCESSOR(CallNamed)
virtual void PrintDataTo(StringStream* stream);
LOperand* context() { return inputs_[0]; }
Handle<String> name() const { return hydrogen()->name(); }
int arity() const { return hydrogen()->argument_count() - 1; }
};
class LCallFunction: public LTemplateInstruction<1, 0, 0> {
class LCallFunction: public LTemplateInstruction<1, 1, 0> {
public:
explicit LCallFunction(LOperand* context) {
inputs_[0] = context;
}
DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call-function")
DECLARE_HYDROGEN_ACCESSOR(CallFunction)
LOperand* context() { return inputs_[0]; }
int arity() const { return hydrogen()->argument_count() - 2; }
};
class LCallGlobal: public LTemplateInstruction<1, 0, 0> {
class LCallGlobal: public LTemplateInstruction<1, 1, 0> {
public:
explicit LCallGlobal(LOperand* context) {
inputs_[0] = context;
}
DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call-global")
DECLARE_HYDROGEN_ACCESSOR(CallGlobal)
virtual void PrintDataTo(StringStream* stream);
LOperand* context() { return inputs_[0]; }
Handle<String> name() const {return hydrogen()->name(); }
int arity() const { return hydrogen()->argument_count() - 1; }
};
......@@ -1379,10 +1414,11 @@ class LCallKnownGlobal: public LTemplateInstruction<1, 0, 0> {
};
class LCallNew: public LTemplateInstruction<1, 1, 0> {
class LCallNew: public LTemplateInstruction<1, 2, 0> {
public:
explicit LCallNew(LOperand* constructor) {
inputs_[0] = constructor;
LCallNew(LOperand* context, LOperand* constructor) {
inputs_[0] = context;
inputs_[1] = constructor;
}
DECLARE_CONCRETE_INSTRUCTION(CallNew, "call-new")
......@@ -1390,6 +1426,8 @@ class LCallNew: public LTemplateInstruction<1, 1, 0> {
virtual void PrintDataTo(StringStream* stream);
LOperand* context() { return inputs_[0]; }
LOperand* constructor() { return inputs_[1]; }
int arity() const { return hydrogen()->argument_count() - 1; }
};
......@@ -1536,13 +1574,21 @@ class LStoreNamedField: public LStoreNamed {
};
class LStoreNamedGeneric: public LStoreNamed {
class LStoreNamedGeneric: public LTemplateInstruction<0, 3, 0> {
public:
LStoreNamedGeneric(LOperand* obj, LOperand* val)
: LStoreNamed(obj, val) { }
LStoreNamedGeneric(LOperand* context, LOperand* object, LOperand* value) {
inputs_[0] = context;
inputs_[1] = object;
inputs_[2] = value;
}
DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store-named-generic")
DECLARE_HYDROGEN_ACCESSOR(StoreNamedGeneric)
LOperand* context() { return inputs_[0]; }
LOperand* object() { return inputs_[1]; }
LOperand* value() { return inputs_[2]; }
Handle<Object> name() const { return hydrogen()->name(); }
};
......@@ -1575,12 +1621,24 @@ class LStoreKeyedFastElement: public LStoreKeyed {
};
class LStoreKeyedGeneric: public LStoreKeyed {
class LStoreKeyedGeneric: public LTemplateInstruction<0, 4, 0> {
public:
LStoreKeyedGeneric(LOperand* obj, LOperand* key, LOperand* val)
: LStoreKeyed(obj, key, val) { }
LStoreKeyedGeneric(LOperand* context,
LOperand* object,
LOperand* key,
LOperand* value) {
inputs_[0] = context;
inputs_[1] = object;
inputs_[2] = key;
inputs_[3] = value;
}
DECLARE_CONCRETE_INSTRUCTION(StoreKeyedGeneric, "store-keyed-generic")
LOperand* context() { return inputs_[0]; }
LOperand* object() { return inputs_[1]; }
LOperand* key() { return inputs_[2]; }
LOperand* value() { return inputs_[3]; }
};
......@@ -1686,10 +1744,16 @@ class LArrayLiteral: public LTemplateInstruction<1, 0, 0> {
};
class LObjectLiteral: public LTemplateInstruction<1, 0, 0> {
class LObjectLiteral: public LTemplateInstruction<1, 1, 0> {
public:
explicit LObjectLiteral(LOperand* context) {
inputs_[0] = context;
}
DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral, "object-literal")
DECLARE_HYDROGEN_ACCESSOR(ObjectLiteral)
LOperand* context() { return inputs_[0]; }
};
......
......@@ -78,11 +78,6 @@ void MacroAssembler::RecordWrite(Register object,
int offset,
Register value,
Register scratch) {
// The compiled code assumes that record write doesn't change the
// context register, so we check that none of the clobbered
// registers are esi.
ASSERT(!object.is(esi) && !value.is(esi) && !scratch.is(esi));
// First, check if a write barrier is even needed. The tests below
// catch stores of Smis and stores into young gen.
NearLabel done;
......@@ -129,11 +124,6 @@ void MacroAssembler::RecordWrite(Register object,
void MacroAssembler::RecordWrite(Register object,
Register address,
Register value) {
// The compiled code assumes that record write doesn't change the
// context register, so we check that none of the clobbered
// registers are esi.
ASSERT(!object.is(esi) && !value.is(esi) && !address.is(esi));
// First, check if a write barrier is even needed. The tests below
// catch stores of Smis and stores into young gen.
Label done;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment