Commit 5765fa25 authored by sanjoy@chromium.org's avatar sanjoy@chromium.org

Defer creating Handles for HConstants to the code generation phase.

BUG=
TEST=

Review URL: https://chromiumcodereview.appspot.com/10544196

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12048 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 2f43f5e9
......@@ -322,7 +322,8 @@ Register LCodeGen::EmitLoadRegister(LOperand* op, Register scratch) {
return ToRegister(op->index());
} else if (op->IsConstantOperand()) {
LConstantOperand* const_op = LConstantOperand::cast(op);
Handle<Object> literal = chunk_->LookupLiteral(const_op);
HConstant* constant = chunk_->LookupConstant(const_op);
Handle<Object> literal = constant->handle();
Representation r = chunk_->LookupLiteralRepresentation(const_op);
if (r.IsInteger32()) {
ASSERT(literal->IsNumber());
......@@ -360,7 +361,8 @@ DoubleRegister LCodeGen::EmitLoadDoubleRegister(LOperand* op,
return ToDoubleRegister(op->index());
} else if (op->IsConstantOperand()) {
LConstantOperand* const_op = LConstantOperand::cast(op);
Handle<Object> literal = chunk_->LookupLiteral(const_op);
HConstant* constant = chunk_->LookupConstant(const_op);
Handle<Object> literal = constant->handle();
Representation r = chunk_->LookupLiteralRepresentation(const_op);
if (r.IsInteger32()) {
ASSERT(literal->IsNumber());
......@@ -386,9 +388,9 @@ DoubleRegister LCodeGen::EmitLoadDoubleRegister(LOperand* op,
Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
Handle<Object> literal = chunk_->LookupLiteral(op);
HConstant* constant = chunk_->LookupConstant(op);
ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged());
return literal;
return constant->handle();
}
......@@ -398,33 +400,33 @@ bool LCodeGen::IsInteger32(LConstantOperand* op) const {
int LCodeGen::ToInteger32(LConstantOperand* op) const {
Handle<Object> value = chunk_->LookupLiteral(op);
HConstant* constant = chunk_->LookupConstant(op);
ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32());
ASSERT(static_cast<double>(static_cast<int32_t>(value->Number())) ==
value->Number());
return static_cast<int32_t>(value->Number());
ASSERT(constant->HasInteger32Value());
return constant->Integer32Value();
}
double LCodeGen::ToDouble(LConstantOperand* op) const {
Handle<Object> value = chunk_->LookupLiteral(op);
return value->Number();
HConstant* constant = chunk_->LookupConstant(op);
ASSERT(constant->HasDoubleValue());
return constant->DoubleValue();
}
Operand LCodeGen::ToOperand(LOperand* op) {
if (op->IsConstantOperand()) {
LConstantOperand* const_op = LConstantOperand::cast(op);
Handle<Object> literal = chunk_->LookupLiteral(const_op);
HConstant* constant = chunk()->LookupConstant(const_op);
Representation r = chunk_->LookupLiteralRepresentation(const_op);
if (r.IsInteger32()) {
ASSERT(literal->IsNumber());
return Operand(static_cast<int32_t>(literal->Number()));
ASSERT(constant->HasInteger32Value());
return Operand(constant->Integer32Value());
} else if (r.IsDouble()) {
Abort("ToOperand Unsupported double immediate.");
}
ASSERT(r.IsTagged());
return Operand(literal);
return Operand(constant->handle());
} else if (op->IsRegister()) {
return Operand(ToRegister(op));
} else if (op->IsDoubleRegister()) {
......@@ -553,8 +555,8 @@ void LCodeGen::AddToTranslation(Translation* translation,
DoubleRegister reg = ToDoubleRegister(op);
translation->StoreDoubleRegister(reg);
} else if (op->IsConstantOperand()) {
Handle<Object> literal = chunk()->LookupLiteral(LConstantOperand::cast(op));
int src_index = DefineDeoptimizationLiteral(literal);
HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op));
int src_index = DefineDeoptimizationLiteral(constant->handle());
translation->StoreLiteral(src_index);
} else {
UNREACHABLE();
......
......@@ -1385,41 +1385,78 @@ void HEnterInlined::PrintDataTo(StringStream* stream) {
}
static bool IsInteger32(double value) {
double roundtrip_value = static_cast<double>(static_cast<int32_t>(value));
return BitCast<int64_t>(roundtrip_value) == BitCast<int64_t>(value);
}
HConstant::HConstant(Handle<Object> handle, Representation r)
: handle_(handle),
has_int32_value_(false),
has_double_value_(false),
int32_value_(0),
double_value_(0) {
has_double_value_(false) {
set_representation(r);
SetFlag(kUseGVN);
if (handle_->IsNumber()) {
double n = handle_->Number();
double roundtrip_value = static_cast<double>(static_cast<int32_t>(n));
has_int32_value_ = BitCast<int64_t>(roundtrip_value) == BitCast<int64_t>(n);
if (has_int32_value_) int32_value_ = static_cast<int32_t>(n);
has_int32_value_ = IsInteger32(n);
int32_value_ = DoubleToInt32(n);
double_value_ = n;
has_double_value_ = true;
}
}
HConstant::HConstant(int32_t integer_value, Representation r)
: has_int32_value_(true),
has_double_value_(true),
int32_value_(integer_value),
double_value_(FastI2D(integer_value)) {
set_representation(r);
SetFlag(kUseGVN);
}
HConstant::HConstant(double double_value, Representation r)
: has_int32_value_(IsInteger32(double_value)),
has_double_value_(true),
int32_value_(DoubleToInt32(double_value)),
double_value_(double_value) {
set_representation(r);
SetFlag(kUseGVN);
}
HConstant* HConstant::CopyToRepresentation(Representation r, Zone* zone) const {
if (r.IsInteger32() && !has_int32_value_) return NULL;
if (r.IsDouble() && !has_double_value_) return NULL;
if (handle_.is_null()) {
ASSERT(has_int32_value_ || has_double_value_);
if (has_int32_value_) return new(zone) HConstant(int32_value_, r);
return new(zone) HConstant(double_value_, r);
}
return new(zone) HConstant(handle_, r);
}
HConstant* HConstant::CopyToTruncatedInt32(Zone* zone) const {
if (!has_double_value_) return NULL;
int32_t truncated = NumberToInt32(*handle_);
return new(zone) HConstant(FACTORY->NewNumberFromInt(truncated),
Representation::Integer32());
if (has_int32_value_) {
if (handle_.is_null()) {
return new(zone) HConstant(int32_value_, Representation::Integer32());
} else {
// Re-use the existing Handle if possible.
return new(zone) HConstant(handle_, Representation::Integer32());
}
} else if (has_double_value_) {
return new(zone) HConstant(DoubleToInt32(double_value_),
Representation::Integer32());
} else {
return NULL;
}
}
bool HConstant::ToBoolean() const {
bool HConstant::ToBoolean() {
// Converts the constant's boolean value according to
// ECMAScript section 9.2 ToBoolean conversion.
if (HasInteger32Value()) return Integer32Value() != 0;
......@@ -1427,17 +1464,25 @@ bool HConstant::ToBoolean() const {
double v = DoubleValue();
return v != 0 && !isnan(v);
}
if (handle()->IsTrue()) return true;
if (handle()->IsFalse()) return false;
if (handle()->IsUndefined()) return false;
if (handle()->IsNull()) return false;
if (handle()->IsString() &&
String::cast(*handle())->length() == 0) return false;
Handle<Object> literal = handle();
if (literal->IsTrue()) return true;
if (literal->IsFalse()) return false;
if (literal->IsUndefined()) return false;
if (literal->IsNull()) return false;
if (literal->IsString() && String::cast(*literal)->length() == 0) {
return false;
}
return true;
}
void HConstant::PrintDataTo(StringStream* stream) {
handle()->ShortPrint(stream);
if (has_int32_value_) {
stream->Add("%d ", int32_value_);
} else if (has_double_value_) {
stream->Add("%lf ", double_value_);
} else {
handle()->ShortPrint(stream);
}
}
......@@ -2089,6 +2134,10 @@ HType HPhi::CalculateInferredType() {
HType HConstant::CalculateInferredType() {
if (has_int32_value_) {
return Smi::IsValid(int32_value_) ? HType::Smi() : HType::HeapNumber();
}
if (has_double_value_) return HType::HeapNumber();
return HType::TypeFromValue(handle_);
}
......
......@@ -2453,20 +2453,42 @@ class HArgumentsObject: public HTemplateInstruction<0> {
class HConstant: public HTemplateInstruction<0> {
public:
HConstant(Handle<Object> handle, Representation r);
HConstant(int32_t value, Representation r);
HConstant(double value, Representation r);
Handle<Object> handle() const { return handle_; }
Handle<Object> handle() {
if (handle_.is_null()) {
handle_ = FACTORY->NewNumber(double_value_, TENURED);
}
ASSERT(has_int32_value_ || !handle_->IsSmi());
return handle_;
}
bool InOldSpace() const { return !HEAP->InNewSpace(*handle_); }
bool ImmortalImmovable() const {
if (has_int32_value_) {
return false;
}
if (has_double_value_) {
if (BitCast<int64_t>(double_value_) == BitCast<int64_t>(-0.0) ||
isnan(double_value_)) {
return true;
}
return false;
}
ASSERT(!handle_.is_null());
Heap* heap = HEAP;
// We should have handled minus_zero_value and nan_value in the
// has_double_value_ clause above.
ASSERT(*handle_ != heap->minus_zero_value());
ASSERT(*handle_ != heap->nan_value());
if (*handle_ == heap->undefined_value()) return true;
if (*handle_ == heap->null_value()) return true;
if (*handle_ == heap->true_value()) return true;
if (*handle_ == heap->false_value()) return true;
if (*handle_ == heap->the_hole_value()) return true;
if (*handle_ == heap->minus_zero_value()) return true;
if (*handle_ == heap->nan_value()) return true;
if (*handle_ == heap->empty_string()) return true;
return false;
}
......@@ -2476,18 +2498,14 @@ class HConstant: public HTemplateInstruction<0> {
}
virtual bool IsConvertibleToInteger() const {
if (handle_->IsSmi()) return true;
if (handle_->IsHeapNumber() &&
(HeapNumber::cast(*handle_)->value() ==
static_cast<double>(NumberToInt32(*handle_)))) return true;
return false;
return has_int32_value_;
}
virtual bool EmitAtUses() { return !representation().IsDouble(); }
virtual HValue* Canonicalize();
virtual void PrintDataTo(StringStream* stream);
virtual HType CalculateInferredType();
bool IsInteger() const { return handle_->IsSmi(); }
bool IsInteger() { return handle()->IsSmi(); }
HConstant* CopyToRepresentation(Representation r, Zone* zone) const;
HConstant* CopyToTruncatedInt32(Zone* zone) const;
bool HasInteger32Value() const { return has_int32_value_; }
......@@ -2500,24 +2518,31 @@ class HConstant: public HTemplateInstruction<0> {
ASSERT(HasDoubleValue());
return double_value_;
}
bool HasNumberValue() const { return has_int32_value_ || has_double_value_; }
bool HasNumberValue() const { return has_double_value_; }
int32_t NumberValueAsInteger32() const {
ASSERT(HasNumberValue());
if (has_int32_value_) return int32_value_;
return DoubleToInt32(double_value_);
// Irrespective of whether a numeric HConstant can be safely
// represented as an int32, we store the (in some cases lossy)
// representation of the number in int32_value_.
return int32_value_;
}
bool HasStringValue() const { return handle_->IsString(); }
bool ToBoolean() const;
bool ToBoolean();
virtual intptr_t Hashcode() {
ASSERT(!HEAP->allow_allocation(false));
intptr_t hash = reinterpret_cast<intptr_t>(*handle());
// Prevent smis from having fewer hash values when truncated to
// the least significant bits.
const int kShiftSize = kSmiShiftSize + kSmiTagSize;
STATIC_ASSERT(kShiftSize != 0);
return hash ^ (hash >> kShiftSize);
intptr_t hash;
if (has_int32_value_) {
hash = static_cast<intptr_t>(int32_value_);
} else if (has_double_value_) {
hash = static_cast<intptr_t>(BitCast<int64_t>(double_value_));
} else {
ASSERT(!handle_.is_null());
hash = reinterpret_cast<intptr_t>(*handle_);
}
return hash;
}
#ifdef DEBUG
......@@ -2531,15 +2556,32 @@ class HConstant: public HTemplateInstruction<0> {
virtual bool DataEquals(HValue* other) {
HConstant* other_constant = HConstant::cast(other);
return handle().is_identical_to(other_constant->handle());
if (has_int32_value_) {
return other_constant->has_int32_value_ &&
int32_value_ == other_constant->int32_value_;
} else if (has_double_value_) {
return other_constant->has_double_value_ &&
BitCast<int64_t>(double_value_) ==
BitCast<int64_t>(other_constant->double_value_);
} else {
ASSERT(!handle_.is_null());
return !other_constant->handle_.is_null() &&
*handle_ == *other_constant->handle_;
}
}
private:
// If this is a numerical constant, handle_ either points to to the
// HeapObject the constant originated from or is null. If the
// constant is non-numeric, handle_ always points to a valid
// constant HeapObject.
Handle<Object> handle_;
// The following two values represent the int32 and the double value of the
// given constant if there is a lossless conversion between the constant
// and the specific representation.
// We store the HConstant in the most specific form safely possible.
// The two flags, has_int32_value_ and has_double_value_ tell us if
// int32_value_ and double_value_ hold valid, safe representations
// of the constant. has_int32_value_ implies has_double_value_ but
// not the converse.
bool has_int32_value_ : 1;
bool has_double_value_ : 1;
int32_t int32_value_;
......
......@@ -579,13 +579,25 @@ HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer,
}
HConstant* HGraph::GetConstantInt32(SetOncePointer<HConstant>* pointer,
int32_t value) {
if (!pointer->is_set()) {
HConstant* constant =
new(zone()) HConstant(value, Representation::Integer32());
constant->InsertAfter(GetConstantUndefined());
pointer->set(constant);
}
return pointer->get();
}
HConstant* HGraph::GetConstant1() {
return GetConstant(&constant_1_, Handle<Smi>(Smi::FromInt(1)));
return GetConstantInt32(&constant_1_, 1);
}
HConstant* HGraph::GetConstantMinus1() {
return GetConstant(&constant_minus1_, Handle<Smi>(Smi::FromInt(-1)));
return GetConstantInt32(&constant_minus1_, -1);
}
......@@ -3378,8 +3390,7 @@ class BoundsCheckBbData: public ZoneObject {
Representation representation,
int32_t new_offset) {
HConstant* new_constant = new(BasicBlock()->zone())
HConstant(Handle<Object>(Smi::FromInt(new_offset)),
Representation::Integer32());
HConstant(new_offset, Representation::Integer32());
if (*add == NULL) {
new_constant->InsertBefore(check);
*add = new(BasicBlock()->zone()) HAdd(NULL,
......@@ -7908,8 +7919,8 @@ HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
// for a smi operation. If one of the operands is a constant string
// do not generate code assuming it is a smi operation.
if (info.IsSmi() &&
((left->IsConstant() && HConstant::cast(left)->HasStringValue()) ||
(right->IsConstant() && HConstant::cast(right)->HasStringValue()))) {
((left->IsConstant() && HConstant::cast(left)->handle()->IsString()) ||
(right->IsConstant() && HConstant::cast(right)->handle()->IsString()))) {
return instr;
}
Representation rep = ToRepresentation(info);
......@@ -8127,7 +8138,7 @@ static bool MatchLiteralCompareTypeof(HValue* left,
if (left->IsTypeof() &&
Token::IsEqualityOp(op) &&
right->IsConstant() &&
HConstant::cast(right)->HasStringValue()) {
HConstant::cast(right)->handle()->IsString()) {
*typeof_expr = HTypeof::cast(left);
*check = Handle<String>::cast(HConstant::cast(right)->handle());
return true;
......
......@@ -348,6 +348,8 @@ class HGraph: public ZoneObject {
private:
HConstant* GetConstant(SetOncePointer<HConstant>* pointer,
Handle<Object> value);
HConstant* GetConstantInt32(SetOncePointer<HConstant>* pointer,
int32_t integer_value);
void MarkAsDeoptimizingRecursively(HBasicBlock* block);
void InsertTypeConversions(HInstruction* instr);
......
......@@ -360,24 +360,24 @@ XMMRegister LCodeGen::ToDoubleRegister(LOperand* op) const {
int LCodeGen::ToInteger32(LConstantOperand* op) const {
Handle<Object> value = chunk_->LookupLiteral(op);
HConstant* constant = chunk_->LookupConstant(op);
ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32());
ASSERT(static_cast<double>(static_cast<int32_t>(value->Number())) ==
value->Number());
return static_cast<int32_t>(value->Number());
ASSERT(constant->HasInteger32Value());
return constant->Integer32Value();
}
Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
Handle<Object> literal = chunk_->LookupLiteral(op);
HConstant* constant = chunk_->LookupConstant(op);
ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged());
return literal;
return constant->handle();
}
double LCodeGen::ToDouble(LConstantOperand* op) const {
Handle<Object> value = chunk_->LookupLiteral(op);
return value->Number();
HConstant* constant = chunk_->LookupConstant(op);
ASSERT(constant->HasDoubleValue());
return constant->DoubleValue();
}
......@@ -494,8 +494,8 @@ void LCodeGen::AddToTranslation(Translation* translation,
XMMRegister reg = ToDoubleRegister(op);
translation->StoreDoubleRegister(reg);
} else if (op->IsConstantOperand()) {
Handle<Object> literal = chunk()->LookupLiteral(LConstantOperand::cast(op));
int src_index = DefineDeoptimizationLiteral(literal);
HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op));
int src_index = DefineDeoptimizationLiteral(constant->handle());
translation->StoreLiteral(src_index);
} else {
UNREACHABLE();
......@@ -554,9 +554,9 @@ void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
} else if (context->IsStackSlot()) {
__ mov(esi, ToOperand(context));
} else if (context->IsConstantOperand()) {
Handle<Object> literal =
chunk_->LookupLiteral(LConstantOperand::cast(context));
__ LoadHeapObject(esi, Handle<Context>::cast(literal));
HConstant* constant =
chunk_->LookupConstant(LConstantOperand::cast(context));
__ LoadHeapObject(esi, Handle<Context>::cast(constant->handle()));
} else {
UNREACHABLE();
}
......
......@@ -375,8 +375,8 @@ void LChunkBase::AddGapMove(int index, LOperand* from, LOperand* to) {
}
Handle<Object> LChunkBase::LookupLiteral(LConstantOperand* operand) const {
return HConstant::cast(graph_->LookupValue(operand->index()))->handle();
HConstant* LChunkBase::LookupConstant(LConstantOperand* operand) const {
return HConstant::cast(graph_->LookupValue(operand->index()));
}
......
......@@ -639,7 +639,7 @@ class LChunkBase: public ZoneObject {
void AddInstruction(LInstruction* instruction, HBasicBlock* block);
LConstantOperand* DefineConstantOperand(HConstant* constant);
Handle<Object> LookupLiteral(LConstantOperand* operand) const;
HConstant* LookupConstant(LConstantOperand* operand) const;
Representation LookupLiteralRepresentation(LConstantOperand* operand) const;
int ParameterAt(int index);
......
......@@ -320,24 +320,24 @@ bool LCodeGen::IsTaggedConstant(LConstantOperand* op) const {
int LCodeGen::ToInteger32(LConstantOperand* op) const {
Handle<Object> value = chunk_->LookupLiteral(op);
HConstant* constant = chunk_->LookupConstant(op);
ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32());
ASSERT(static_cast<double>(static_cast<int32_t>(value->Number())) ==
value->Number());
return static_cast<int32_t>(value->Number());
ASSERT(constant->HasInteger32Value());
return constant->Integer32Value();
}
double LCodeGen::ToDouble(LConstantOperand* op) const {
Handle<Object> value = chunk_->LookupLiteral(op);
return value->Number();
HConstant* constant = chunk_->LookupConstant(op);
ASSERT(constant->HasDoubleValue());
return constant->DoubleValue();
}
Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
Handle<Object> literal = chunk_->LookupLiteral(op);
HConstant* constant = chunk_->LookupConstant(op);
ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged());
return literal;
return constant->handle();
}
......@@ -442,8 +442,8 @@ void LCodeGen::AddToTranslation(Translation* translation,
XMMRegister reg = ToDoubleRegister(op);
translation->StoreDoubleRegister(reg);
} else if (op->IsConstantOperand()) {
Handle<Object> literal = chunk()->LookupLiteral(LConstantOperand::cast(op));
int src_index = DefineDeoptimizationLiteral(literal);
HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op));
int src_index = DefineDeoptimizationLiteral(constant->handle());
translation->StoreLiteral(src_index);
} else {
UNREACHABLE();
......
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