Clean up the Result class. Reduce the size of Result from four words

to one by keeping a stack of active code generators and by using
indirection to handles.

Mainly a cleanup.  No visible performance impact.
Review URL: http://codereview.chromium.org/113455

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1965 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
ager@chromium.org 2009-05-15 11:09:51 +00:00
parent ed72ecb02e
commit a3f30f5a3a
12 changed files with 175 additions and 124 deletions

View File

@ -40,6 +40,10 @@
namespace v8 { namespace internal {
CodeGenerator* CodeGeneratorScope::top_ = NULL;
DeferredCode::DeferredCode(CodeGenerator* generator)
: generator_(generator),
masm_(generator->masm()),
@ -154,6 +158,7 @@ Handle<Code> CodeGenerator::MakeCode(FunctionLiteral* flit,
// Generate code.
const int initial_buffer_size = 4 * KB;
CodeGenerator cgen(initial_buffer_size, script, is_eval);
CodeGeneratorScope scope(&cgen);
cgen.GenCode(flit);
if (cgen.HasStackOverflow()) {
ASSERT(!Top::has_pending_exception());

View File

@ -86,9 +86,35 @@ enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
#include "arm/codegen-arm.h"
#endif
#include "register-allocator.h"
namespace v8 { namespace internal {
// Code generation can be nested. Code generation scopes form a stack
// of active code generators.
class CodeGeneratorScope BASE_EMBEDDED {
public:
explicit CodeGeneratorScope(CodeGenerator* cgen) {
previous_ = top_;
top_ = cgen;
}
~CodeGeneratorScope() {
top_ = previous_;
}
static CodeGenerator* Current() {
ASSERT(top_ != NULL);
return top_;
}
private:
static CodeGenerator* top_;
CodeGenerator* previous_;
};
// Use lazy compilation; defaults to true.
// NOTE: Do not remove non-lazy compilation until we can properly
// install extensions with lazy compilation enabled. At the

View File

@ -79,7 +79,10 @@ class CompilationZoneScope : public ZoneScope {
public:
explicit CompilationZoneScope(ZoneScopeMode mode) : ZoneScope(mode) { }
virtual ~CompilationZoneScope() {
if (ShouldDeleteOnExit()) FrameElement::ClearConstantList();
if (ShouldDeleteOnExit()) {
FrameElement::ClearConstantList();
Result::ClearConstantList();
}
}
};

View File

@ -281,7 +281,7 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
ASSERT(!function_return_is_shadowed_);
CodeForReturnPosition(fun);
frame_->PrepareForReturn();
Result undefined(Factory::undefined_value(), this);
Result undefined(Factory::undefined_value());
if (function_return_.is_bound()) {
function_return_.Jump(&undefined);
} else {
@ -296,7 +296,7 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
// control does not flow off the end of the body so we did not
// compile an artificial return statement just above, and (b) there
// are return statements in the body but (c) they are all shadowed.
Result return_value(this);
Result return_value;
// Though this is a (possibly) backward block, the frames can
// only differ on their top element.
function_return_.Bind(&return_value, 1);
@ -388,7 +388,7 @@ Operand CodeGenerator::ContextSlotOperandCheckExtensions(Slot* slot,
JumpTarget* slow) {
ASSERT(slot->type() == Slot::CONTEXT);
ASSERT(tmp.is_register());
Result context(esi, this);
Result context(esi);
for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) {
if (s->num_heap_slots() > 0) {
@ -803,8 +803,8 @@ class DeferredInlineBinaryOperation: public DeferredCode {
void DeferredInlineBinaryOperation::Generate() {
Result left(generator());
Result right(generator());
Result left;
Result right;
enter()->Bind(&left, &right);
generator()->frame()->Push(&left);
generator()->frame()->Push(&right);
@ -859,7 +859,7 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
if (left_is_string || right_is_string) {
frame_->Push(&left);
frame_->Push(&right);
Result answer(this);
Result answer;
if (left_is_string) {
if (right_is_string) {
// TODO(lrn): if (left.is_constant() && right.is_constant())
@ -1045,7 +1045,7 @@ class DeferredInlineSmiOperation: public DeferredCode {
void DeferredInlineSmiOperation::Generate() {
Result left(generator());
Result left;
enter()->Bind(&left);
generator()->frame()->Push(&left);
generator()->frame()->Push(value_);
@ -1078,7 +1078,7 @@ class DeferredInlineSmiOperationReversed: public DeferredCode {
void DeferredInlineSmiOperationReversed::Generate() {
Result right(generator());
Result right;
enter()->Bind(&right);
generator()->frame()->Push(value_);
generator()->frame()->Push(&right);
@ -1109,7 +1109,7 @@ class DeferredInlineSmiAdd: public DeferredCode {
void DeferredInlineSmiAdd::Generate() {
// Undo the optimistic add operation and call the shared stub.
Result left(generator()); // Initially left + value_.
Result left; // Initially left + value_.
enter()->Bind(&left);
left.ToRegister();
generator()->frame()->Spill(left.reg());
@ -1143,7 +1143,7 @@ class DeferredInlineSmiAddReversed: public DeferredCode {
void DeferredInlineSmiAddReversed::Generate() {
// Undo the optimistic add operation and call the shared stub.
Result right(generator()); // Initially value_ + right.
Result right; // Initially value_ + right.
enter()->Bind(&right);
right.ToRegister();
generator()->frame()->Spill(right.reg());
@ -1177,7 +1177,7 @@ class DeferredInlineSmiSub: public DeferredCode {
void DeferredInlineSmiSub::Generate() {
// Undo the optimistic sub operation and call the shared stub.
Result left(generator()); // Initially left - value_.
Result left; // Initially left - value_.
enter()->Bind(&left);
left.ToRegister();
generator()->frame()->Spill(left.reg());
@ -1211,7 +1211,7 @@ class DeferredInlineSmiSubReversed: public DeferredCode {
void DeferredInlineSmiSubReversed::Generate() {
// Call the shared stub.
Result right(generator());
Result right;
enter()->Bind(&right);
generator()->frame()->Push(value_);
generator()->frame()->Push(&right);
@ -1235,7 +1235,7 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
// TODO(199): Optimize some special cases of operations involving a
// smi literal (multiply by 2, shift by 0, etc.).
if (IsUnsafeSmi(value)) {
Result unsafe_operand(value, this);
Result unsafe_operand(value);
if (reversed) {
LikelySmiBinaryOperation(op, &unsafe_operand, operand,
overwrite_mode);
@ -1275,7 +1275,7 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
case Token::SUB: {
DeferredCode* deferred = NULL;
Result answer(this); // Only allocate a new register if reversed.
Result answer; // Only allocate a new register if reversed.
if (reversed) {
answer = allocator()->Allocate();
ASSERT(answer.is_valid());
@ -1304,7 +1304,7 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
case Token::SAR: {
if (reversed) {
Result constant_operand(value, this);
Result constant_operand(value);
LikelySmiBinaryOperation(op, &constant_operand, operand,
overwrite_mode);
} else {
@ -1330,7 +1330,7 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
case Token::SHR: {
if (reversed) {
Result constant_operand(value, this);
Result constant_operand(value);
LikelySmiBinaryOperation(op, &constant_operand, operand,
overwrite_mode);
} else {
@ -1365,7 +1365,7 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
case Token::SHL: {
if (reversed) {
Result constant_operand(value, this);
Result constant_operand(value);
LikelySmiBinaryOperation(op, &constant_operand, operand,
overwrite_mode);
} else {
@ -1435,7 +1435,7 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
}
default: {
Result constant_operand(value, this);
Result constant_operand(value);
if (reversed) {
LikelySmiBinaryOperation(op, &constant_operand, operand,
overwrite_mode);
@ -1484,8 +1484,8 @@ void CodeGenerator::Comparison(Condition cc,
// Strict only makes sense for equality comparisons.
ASSERT(!strict || cc == equal);
Result left_side(this);
Result right_side(this);
Result left_side;
Result right_side;
// Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order.
if (cc == greater || cc == less_equal) {
cc = ReverseCondition(cc);
@ -1769,7 +1769,7 @@ void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
frame_->Push(pairs);
// Duplicate the context register.
Result context(esi, this);
Result context(esi);
frame_->Push(&context);
frame_->Push(Smi::FromInt(is_eval() ? 1 : 0));
@ -1793,7 +1793,7 @@ void CodeGenerator::VisitDeclaration(Declaration* node) {
// during variable resolution and must have mode DYNAMIC.
ASSERT(var->is_dynamic());
// For now, just do a runtime call. Duplicate the context register.
Result context(esi, this);
Result context(esi);
frame_->Push(&context);
frame_->Push(var->name());
// Declaration nodes are always introduced in one of two modes.
@ -2032,7 +2032,7 @@ void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) {
Comment cmnt(masm_, "[ WithEnterStatement");
CodeForStatementPosition(node);
Load(node->expression());
Result context(this);
Result context;
if (node->is_catch_block()) {
context = frame_->CallRuntime(Runtime::kPushCatchContext, 1);
} else {
@ -2941,7 +2941,7 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) {
// Generate unlink code for the (formerly) shadowing targets that
// have been jumped to. Deallocate each shadow target.
Result return_value(this);
Result return_value;
for (int i = 0; i < shadows.length(); i++) {
if (shadows[i]->is_linked()) {
// Unlink from try chain; be careful not to destroy the TOS if
@ -3073,7 +3073,7 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
// on the virtual frame. We must preserve it until it is
// pushed.
if (i == kReturnShadowIndex) {
Result return_value(this);
Result return_value;
shadows[i]->Bind(&return_value);
return_value.ToRegister(eax);
} else {
@ -3256,7 +3256,7 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
JumpTarget slow(this);
JumpTarget done(this);
Result value(this);
Result value;
// Generate fast-case code for variables that might be shadowed by
// eval-introduced variables. Eval is used a lot without
@ -3356,7 +3356,7 @@ Result CodeGenerator::LoadFromGlobalSlotCheckExtensions(
JumpTarget* slow) {
// Check that no extension objects have been created by calls to
// eval from the current scope to the global scope.
Result context(esi, this);
Result context(esi);
Result tmp = allocator_->Allocate();
ASSERT(tmp.is_valid()); // All non-reserved registers were available.
@ -3431,7 +3431,7 @@ void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) {
frame_->Push(esi);
frame_->Push(slot->var()->name());
Result value(this);
Result value;
if (init_state == CONST_INIT) {
// Same as the case for a normal store, but ignores attribute
// (e.g. READ_ONLY) of context slot so that we can initialize const
@ -3574,7 +3574,7 @@ class DeferredRegExpLiteral: public DeferredCode {
void DeferredRegExpLiteral::Generate() {
Result literals(generator());
Result literals;
enter()->Bind(&literals);
// Since the entry is undefined we call the runtime system to
// compute the literal.
@ -3651,7 +3651,7 @@ class DeferredObjectLiteral: public DeferredCode {
void DeferredObjectLiteral::Generate() {
Result literals(generator());
Result literals;
enter()->Bind(&literals);
// Since the entry is undefined we call the runtime system to
// compute the literal.
@ -3789,7 +3789,7 @@ class DeferredArrayLiteral: public DeferredCode {
void DeferredArrayLiteral::Generate() {
Result literals(generator());
Result literals;
enter()->Bind(&literals);
// Since the entry is undefined we call the runtime system to
// compute the literal.
@ -4438,7 +4438,7 @@ void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) {
ASSERT(args->length() == 0);
// ArgumentsAccessStub takes the parameter count as an input argument
// in register eax. Create a constant result for it.
Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters())), this);
Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters())));
// Call the shared stub to get to the arguments.length.
ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH);
Result result = frame_->CallStub(&stub, &count);
@ -4521,7 +4521,7 @@ void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) {
Load(args->at(0));
Result key = frame_->Pop();
// Explicitly create a constant result.
Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters())), this);
Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters())));
// Call the shared stub to get to arguments[key].
ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
Result result = frame_->CallStub(&stub, &key, &count);
@ -4771,7 +4771,7 @@ class DeferredCountOperation: public DeferredCode {
void DeferredCountOperation::Generate() {
CodeGenerator* cgen = generator();
Result value(cgen);
Result value;
enter()->Bind(&value);
VirtualFrame* frame = cgen->frame();
// Undo the optimistic smi operation.
@ -5269,7 +5269,7 @@ class DeferredReferenceGetNamedValue: public DeferredCode {
void DeferredReferenceGetNamedValue::Generate() {
CodeGenerator* cgen = generator();
Result receiver(cgen);
Result receiver;
enter()->Bind(&receiver);
cgen->frame()->Push(&receiver);
@ -5311,8 +5311,8 @@ class DeferredReferenceGetKeyedValue: public DeferredCode {
void DeferredReferenceGetKeyedValue::Generate() {
CodeGenerator* cgen = generator();
Result receiver(cgen);
Result key(cgen);
Result receiver;
Result key;
enter()->Bind(&receiver, &key);
cgen->frame()->Push(&receiver); // First IC argument.
cgen->frame()->Push(&key); // Second IC argument.

View File

@ -38,12 +38,13 @@ namespace v8 { namespace internal {
void Result::ToRegister() {
ASSERT(is_valid());
if (is_constant()) {
Result fresh = cgen_->allocator()->Allocate();
Result fresh = CodeGeneratorScope::Current()->allocator()->Allocate();
ASSERT(fresh.is_valid());
if (cgen_->IsUnsafeSmi(handle())) {
cgen_->LoadUnsafeSmi(fresh.reg(), handle());
if (CodeGeneratorScope::Current()->IsUnsafeSmi(handle())) {
CodeGeneratorScope::Current()->LoadUnsafeSmi(fresh.reg(), handle());
} else {
cgen_->masm()->Set(fresh.reg(), Immediate(handle()));
CodeGeneratorScope::Current()->masm()->Set(fresh.reg(),
Immediate(handle()));
}
// This result becomes a copy of the fresh one.
*this = fresh;
@ -55,23 +56,24 @@ void Result::ToRegister() {
void Result::ToRegister(Register target) {
ASSERT(is_valid());
if (!is_register() || !reg().is(target)) {
Result fresh = cgen_->allocator()->Allocate(target);
Result fresh = CodeGeneratorScope::Current()->allocator()->Allocate(target);
ASSERT(fresh.is_valid());
if (is_register()) {
cgen_->masm()->mov(fresh.reg(), reg());
CodeGeneratorScope::Current()->masm()->mov(fresh.reg(), reg());
} else {
ASSERT(is_constant());
if (cgen_->IsUnsafeSmi(handle())) {
cgen_->LoadUnsafeSmi(fresh.reg(), handle());
if (CodeGeneratorScope::Current()->IsUnsafeSmi(handle())) {
CodeGeneratorScope::Current()->LoadUnsafeSmi(fresh.reg(), handle());
} else {
cgen_->masm()->Set(fresh.reg(), Immediate(handle()));
CodeGeneratorScope::Current()->masm()->Set(fresh.reg(),
Immediate(handle()));
}
}
*this = fresh;
} else if (is_register() && reg().is(target)) {
ASSERT(cgen_->has_valid_frame());
cgen_->frame()->Spill(target);
ASSERT(cgen_->allocator()->count(target) == 1);
ASSERT(CodeGeneratorScope::Current()->has_valid_frame());
CodeGeneratorScope::Current()->frame()->Spill(target);
ASSERT(CodeGeneratorScope::Current()->allocator()->count(target) == 1);
}
ASSERT(is_register());
ASSERT(reg().is(target));
@ -127,7 +129,7 @@ Result RegisterAllocator::AllocateByteRegisterWithoutSpilling() {
// register if valid and return an invalid result.
if (result.is_valid() && !result.reg().is_byte_register()) {
result.Unuse();
return Result(cgen_);
return Result();
}
return result;
}

View File

@ -1075,12 +1075,12 @@ Result VirtualFrame::Pop() {
new_element.set_static_type(element.static_type());
elements_[index] = new_element;
__ mov(temp.reg(), Operand(ebp, fp_relative(index)));
return Result(temp.reg(), cgen_, element.static_type());
return Result(temp.reg(), element.static_type());
} else if (element.is_register()) {
return Result(element.reg(), cgen_, element.static_type());
return Result(element.reg(), element.static_type());
} else {
ASSERT(element.is_constant());
return Result(element.handle(), cgen_);
return Result(element.handle());
}
}

View File

@ -187,7 +187,7 @@ class VirtualFrame : public ZoneObject {
// Set a frame element to a constant. The index is frame-top relative.
void SetElementAt(int index, Handle<Object> value) {
Result temp(value, cgen_);
Result temp(value);
SetElementAt(index, &temp);
}

View File

@ -35,13 +35,25 @@
namespace v8 { namespace internal {
Result::~Result() {
if (is_register()) cgen_->allocator()->Unuse(reg());
if (is_register()) {
CodeGeneratorScope::Current()->allocator()->Unuse(reg());
}
}
void Result::Unuse() {
if (is_register()) cgen_->allocator()->Unuse(reg());
type_ = INVALID;
if (is_register()) {
CodeGeneratorScope::Current()->allocator()->Unuse(reg());
}
invalidate();
}
void Result::CopyTo(Result* destination) const {
destination->value_ = value_;
if (is_register()) {
CodeGeneratorScope::Current()->allocator()->Use(reg());
}
}

View File

@ -35,39 +35,22 @@ namespace v8 { namespace internal {
// -------------------------------------------------------------------------
// Result implementation.
Result::Result(Register reg, CodeGenerator* cgen)
: static_type_(),
type_(REGISTER),
cgen_(cgen) {
data_.reg_ = reg;
Result::Result(Register reg) {
ASSERT(reg.is_valid());
cgen_->allocator()->Use(reg);
CodeGeneratorScope::Current()->allocator()->Use(reg);
value_ = StaticTypeField::encode(StaticType::UNKNOWN_TYPE)
| TypeField::encode(REGISTER)
| DataField::encode(reg.code_);
}
Result::Result(Register reg, CodeGenerator* cgen, StaticType static_type)
: static_type_(static_type),
type_(REGISTER),
cgen_(cgen) {
data_.reg_ = reg;
Result::Result(Register reg, StaticType type) {
ASSERT(reg.is_valid());
cgen_->allocator()->Use(reg);
}
void Result::CopyTo(Result* destination) const {
destination->static_type_ = static_type_;
destination->type_ = type();
destination->cgen_ = cgen_;
if (is_register()) {
destination->data_.reg_ = reg();
cgen_->allocator()->Use(reg());
} else if (is_constant()) {
destination->data_.handle_ = data_.handle_;
} else {
ASSERT(!is_valid());
}
CodeGeneratorScope::Current()->allocator()->Use(reg);
value_ = StaticTypeField::encode(type.static_type_)
| TypeField::encode(REGISTER)
| DataField::encode(reg.code_);
}
@ -80,9 +63,9 @@ Result RegisterAllocator::AllocateWithoutSpilling() {
int free_reg = registers_.ScanForFreeRegister();
if (free_reg < kNumRegisters) {
Register free_result = { free_reg };
return Result(free_result, cgen_);
return Result(free_result);
}
return Result(cgen_);
return Result();
}
@ -94,7 +77,7 @@ Result RegisterAllocator::Allocate() {
Register free_reg = cgen_->frame()->SpillAnyRegister();
if (free_reg.is_valid()) {
ASSERT(!is_used(free_reg));
return Result(free_reg, cgen_);
return Result(free_reg);
}
}
return result;
@ -104,7 +87,7 @@ Result RegisterAllocator::Allocate() {
Result RegisterAllocator::Allocate(Register target) {
// If the target is not referenced, it can simply be allocated.
if (!is_used(target)) {
return Result(target, cgen_);
return Result(target);
}
// If the target is only referenced in the frame, it can be spilled and
// then allocated.
@ -112,10 +95,10 @@ Result RegisterAllocator::Allocate(Register target) {
if (cgen_->frame()->is_used(target) && count(target) == 1) {
cgen_->frame()->Spill(target);
ASSERT(!is_used(target));
return Result(target, cgen_);
return Result(target);
}
// Otherwise (if it's referenced outside the frame) we cannot allocate it.
return Result(cgen_);
return Result();
}

View File

@ -103,6 +103,7 @@ class StaticType BASE_EMBEDDED {
StaticTypeEnum static_type_;
friend class FrameElement;
friend class Result;
};
@ -121,26 +122,20 @@ class Result BASE_EMBEDDED {
};
// Construct an invalid result.
explicit Result(CodeGenerator* cgen)
: static_type_(),
type_(INVALID),
cgen_(cgen) {}
Result() { invalidate(); }
// Construct a register Result.
Result(Register reg,
CodeGenerator* cgen);
explicit Result(Register reg);
// Construct a register Result with a known static type.
Result(Register reg,
CodeGenerator* cgen,
StaticType static_type);
Result(Register reg, StaticType static_type);
// Construct a Result whose value is a compile-time constant.
Result(Handle<Object> value, CodeGenerator * cgen)
: static_type_(StaticType::TypeOf(*value)),
type_(CONSTANT),
cgen_(cgen) {
data_.handle_ = value.location();
explicit Result(Handle<Object> value) {
value_ = StaticTypeField::encode(StaticType::TypeOf(*value).static_type_)
| TypeField::encode(CONSTANT)
| DataField::encode(ConstantList()->length());
ConstantList()->Add(value);
}
// The copy constructor and assignment operators could each create a new
@ -159,25 +154,51 @@ class Result BASE_EMBEDDED {
inline ~Result();
// Static indirection table for handles to constants. If a Result
// represents a constant, the data contains an index into this table
// of handles to the actual constants.
typedef ZoneList<Handle<Object> > ZoneObjectList;
static ZoneObjectList* ConstantList() {
static ZoneObjectList list(10);
return &list;
}
// Clear the constants indirection table.
static void ClearConstantList() {
ConstantList()->Clear();
}
inline void Unuse();
StaticType static_type() const { return static_type_; }
void set_static_type(StaticType static_type) { static_type_ = static_type; }
StaticType static_type() const {
return StaticType(StaticTypeField::decode(value_));
}
Type type() const { return static_cast<Type>(type_); }
void set_static_type(StaticType type) {
value_ = value_ & ~StaticTypeField::mask();
value_ = value_ | StaticTypeField::encode(type.static_type_);
}
Type type() const { return TypeField::decode(value_); }
void invalidate() { value_ = TypeField::encode(INVALID); }
bool is_valid() const { return type() != INVALID; }
bool is_register() const { return type() == REGISTER; }
bool is_constant() const { return type() == CONSTANT; }
Register reg() const {
ASSERT(type() == REGISTER);
return data_.reg_;
ASSERT(is_register());
uint32_t reg = DataField::decode(value_);
Register result;
result.code_ = reg;
return result;
}
Handle<Object> handle() const {
ASSERT(type() == CONSTANT);
return Handle<Object>(data_.handle_);
return ConstantList()->at(DataField::decode(value_));
}
// Move this result to an arbitrary register. The register is not
@ -191,17 +212,15 @@ class Result BASE_EMBEDDED {
void ToRegister(Register reg);
private:
StaticType static_type_;
byte type_;
uint32_t value_;
union {
Register reg_;
Object** handle_;
} data_;
class StaticTypeField: public BitField<StaticType::StaticTypeEnum, 0, 3> {};
class TypeField: public BitField<Type, 3, 2> {};
class DataField: public BitField<uint32_t, 5, 32 - 6> {};
CodeGenerator* cgen_;
inline void CopyTo(Result* destination) const;
void CopyTo(Result* destination) const;
friend class CodeGeneratorScope;
};

View File

@ -324,11 +324,11 @@ void VirtualFrame::SetElementAt(int index, Result* value) {
// Early exit if the element is the same as the one being set.
bool same_register = original.is_register()
&& value->is_register()
&& original.reg().is(value->reg());
&& value->is_register()
&& original.reg().is(value->reg());
bool same_constant = original.is_constant()
&& value->is_constant()
&& original.handle().is_identical_to(value->handle());
&& value->is_constant()
&& original.handle().is_identical_to(value->handle());
if (same_register || same_constant) {
value->Unuse();
return;

View File

@ -13,6 +13,7 @@
#include "top.h"
#include "cctest.h"
#include "disassembler.h"
#include "register-allocator-inl.h"
using v8::Function;
using v8::Local;