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