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,
......
This diff is collapsed.
This diff is collapsed.
...@@ -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);
} }
} }
......
This diff is collapsed.
...@@ -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