}
-Handle<Object> Factory::NewNumberFromInt(int value) {
+Handle<Object> Factory::NewNumberFromInt(int32_t value,
+ PretenureFlag pretenure) {
CALL_HEAP_FUNCTION(
isolate(),
- isolate()->heap()->NumberFromInt32(value), Object);
+ isolate()->heap()->NumberFromInt32(value, pretenure), Object);
}
-Handle<Object> Factory::NewNumberFromUint(uint32_t value) {
+Handle<Object> Factory::NewNumberFromUint(uint32_t value,
+ PretenureFlag pretenure) {
CALL_HEAP_FUNCTION(
isolate(),
- isolate()->heap()->NumberFromUint32(value), Object);
+ isolate()->heap()->NumberFromUint32(value, pretenure), Object);
}
Handle<Object> NewNumber(double value,
PretenureFlag pretenure = NOT_TENURED);
- Handle<Object> NewNumberFromInt(int value);
- Handle<Object> NewNumberFromUint(uint32_t value);
+ Handle<Object> NewNumberFromInt(int32_t value,
+ PretenureFlag pretenure = NOT_TENURED);
+ Handle<Object> NewNumberFromUint(uint32_t value,
+ PretenureFlag pretenure = NOT_TENURED);
// These objects are used by the api to create env-independent data
// structures in the heap.
}
-MaybeObject* Heap::NumberFromInt32(int32_t value) {
+MaybeObject* Heap::NumberFromInt32(
+ int32_t value, PretenureFlag pretenure) {
if (Smi::IsValid(value)) return Smi::FromInt(value);
// Bypass NumberFromDouble to avoid various redundant checks.
- return AllocateHeapNumber(FastI2D(value));
+ return AllocateHeapNumber(FastI2D(value), pretenure);
}
-MaybeObject* Heap::NumberFromUint32(uint32_t value) {
+MaybeObject* Heap::NumberFromUint32(
+ uint32_t value, PretenureFlag pretenure) {
if ((int32_t)value >= 0 && Smi::IsValid((int32_t)value)) {
return Smi::FromInt((int32_t)value);
}
// Bypass NumberFromDouble to avoid various redundant checks.
- return AllocateHeapNumber(FastUI2D(value));
+ return AllocateHeapNumber(FastUI2D(value), pretenure);
}
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed.
// Please note this does not perform a garbage collection.
- MUST_USE_RESULT inline MaybeObject* NumberFromInt32(int32_t value);
+ MUST_USE_RESULT inline MaybeObject* NumberFromInt32(
+ int32_t value, PretenureFlag pretenure = NOT_TENURED);
// Converts an int into either a Smi or a HeapNumber object.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed.
// Please note this does not perform a garbage collection.
- MUST_USE_RESULT inline MaybeObject* NumberFromUint32(uint32_t value);
+ MUST_USE_RESULT inline MaybeObject* NumberFromUint32(
+ uint32_t value, PretenureFlag pretenure = NOT_TENURED);
// Allocates a new foreign object.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
}
+#define H_CONSTANT_INT32(val) \
+new(zone) HConstant(FACTORY->NewNumberFromInt(val, TENURED), \
+ Representation::Integer32())
+#define H_CONSTANT_DOUBLE(val) \
+new(zone) HConstant(FACTORY->NewNumber(val, TENURED), \
+ Representation::Double())
+
+#define DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HInstr, op) \
+HInstruction* HInstr::New##HInstr(Zone* zone, \
+ HValue* context, \
+ HValue* left, \
+ HValue* right) { \
+ if (left->IsConstant() && right->IsConstant()) { \
+ HConstant* c_left = HConstant::cast(left); \
+ HConstant* c_right = HConstant::cast(right); \
+ if ((c_left->HasNumberValue() && c_right->HasNumberValue())) { \
+ double double_res = c_left->DoubleValue() op c_right->DoubleValue(); \
+ if (TypeInfo::IsInt32Double(double_res)) { \
+ return H_CONSTANT_INT32(static_cast<int32_t>(double_res)); \
+ } \
+ return H_CONSTANT_DOUBLE(double_res); \
+ } \
+ } \
+ return new(zone) HInstr(context, left, right); \
+}
+
+
+DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HAdd, +)
+DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HMul, *)
+DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HSub, -)
+
+#undef DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR
+
+
+HInstruction* HMod::NewHMod(Zone* zone,
+ HValue* context,
+ HValue* left,
+ HValue* right) {
+ if (left->IsConstant() && right->IsConstant()) {
+ HConstant* c_left = HConstant::cast(left);
+ HConstant* c_right = HConstant::cast(right);
+ if (c_left->HasInteger32Value() && c_right->HasInteger32Value()) {
+ int32_t dividend = c_left->Integer32Value();
+ int32_t divisor = c_right->Integer32Value();
+ if (divisor != 0) {
+ int32_t res = dividend % divisor;
+ if ((res == 0) && (dividend < 0)) {
+ return H_CONSTANT_DOUBLE(-0.0);
+ }
+ return H_CONSTANT_INT32(res);
+ }
+ }
+ }
+ return new(zone) HMod(context, left, right);
+}
+
+
+HInstruction* HDiv::NewHDiv(Zone* zone,
+ HValue* context,
+ HValue* left,
+ HValue* right) {
+ // If left and right are constant values, try to return a constant value.
+ if (left->IsConstant() && right->IsConstant()) {
+ HConstant* c_left = HConstant::cast(left);
+ HConstant* c_right = HConstant::cast(right);
+ if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
+ if (c_right->DoubleValue() != 0) {
+ double double_res = c_left->DoubleValue() / c_right->DoubleValue();
+ if (TypeInfo::IsInt32Double(double_res)) {
+ return H_CONSTANT_INT32(static_cast<int32_t>(double_res));
+ }
+ return H_CONSTANT_DOUBLE(double_res);
+ }
+ }
+ }
+ return new(zone) HDiv(context, left, right);
+}
+
+
+HInstruction* HBitwise::NewHBitwise(Zone* zone,
+ Token::Value op,
+ HValue* context,
+ HValue* left,
+ HValue* right) {
+ if (left->IsConstant() && right->IsConstant()) {
+ HConstant* c_left = HConstant::cast(left);
+ HConstant* c_right = HConstant::cast(right);
+ if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
+ int32_t result;
+ int32_t v_left = c_left->NumberValueAsInteger32();
+ int32_t v_right = c_right->NumberValueAsInteger32();
+ switch (op) {
+ case Token::BIT_XOR:
+ result = v_left ^ v_right;
+ break;
+ case Token::BIT_AND:
+ result = v_left & v_right;
+ break;
+ case Token::BIT_OR:
+ result = v_left | v_right;
+ break;
+ default:
+ result = 0; // Please the compiler.
+ UNREACHABLE();
+ }
+ return H_CONSTANT_INT32(result);
+ }
+ }
+ return new(zone) HBitwise(op, context, left, right);
+}
+
+
+#define DEFINE_NEW_H_BITWISE_INSTR(HInstr, result) \
+HInstruction* HInstr::New##HInstr(Zone* zone, \
+ HValue* context, \
+ HValue* left, \
+ HValue* right) { \
+ if (left->IsConstant() && right->IsConstant()) { \
+ HConstant* c_left = HConstant::cast(left); \
+ HConstant* c_right = HConstant::cast(right); \
+ if ((c_left->HasNumberValue() && c_right->HasNumberValue())) { \
+ return H_CONSTANT_INT32(result); \
+ } \
+ } \
+ return new(zone) HInstr(context, left, right); \
+}
+
+
+DEFINE_NEW_H_BITWISE_INSTR(HSar,
+c_left->NumberValueAsInteger32() >> (c_right->NumberValueAsInteger32() & 0x1f))
+DEFINE_NEW_H_BITWISE_INSTR(HShl,
+c_left->NumberValueAsInteger32() << (c_right->NumberValueAsInteger32() & 0x1f))
+
+#undef DEFINE_NEW_H_BITWISE_INSTR
+
+
+HInstruction* HShr::NewHShr(Zone* zone,
+ HValue* context,
+ HValue* left,
+ HValue* right) {
+ if (left->IsConstant() && right->IsConstant()) {
+ HConstant* c_left = HConstant::cast(left);
+ HConstant* c_right = HConstant::cast(right);
+ if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
+ int32_t left_val = c_left->NumberValueAsInteger32();
+ int32_t right_val = c_right->NumberValueAsInteger32() & 0x1f;
+ if ((right_val == 0) && (left_val < 0)) {
+ return H_CONSTANT_DOUBLE(
+ static_cast<double>(static_cast<uint32_t>(left_val)));
+ }
+ return H_CONSTANT_INT32(static_cast<uint32_t>(left_val) >> right_val);
+ }
+ }
+ return new(zone) HShr(context, left, right);
+}
+
+
+#undef H_CONSTANT_INT32
+#undef H_CONSTANT_DOUBLE
+
+
void HIn::PrintDataTo(StringStream* stream) {
key()->PrintNameTo(stream);
stream->Add(" ");
ASSERT(HasDoubleValue());
return double_value_;
}
+ bool HasNumberValue() const { return has_int32_value_ || has_double_value_; }
+ int32_t NumberValueAsInteger32() const {
+ ASSERT(HasNumberValue());
+ if (has_int32_value_) return int32_value_;
+ return DoubleToInt32(double_value_);
+ }
bool HasStringValue() const { return handle_->IsString(); }
bool ToBoolean() const;
virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
+ static HInstruction* NewHAdd(Zone* zone,
+ HValue* context,
+ HValue* left,
+ HValue* right);
+
virtual HType CalculateInferredType();
DECLARE_CONCRETE_INSTRUCTION(Add)
virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
+ static HInstruction* NewHSub(Zone* zone,
+ HValue* context,
+ HValue* left,
+ HValue* right);
+
DECLARE_CONCRETE_INSTRUCTION(Sub)
protected:
return !representation().IsTagged();
}
+ static HInstruction* NewHMul(Zone* zone,
+ HValue* context,
+ HValue* left,
+ HValue* right);
+
DECLARE_CONCRETE_INSTRUCTION(Mul)
protected:
virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
+ static HInstruction* NewHMod(Zone* zone,
+ HValue* context,
+ HValue* left,
+ HValue* right);
+
DECLARE_CONCRETE_INSTRUCTION(Mod)
protected:
virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
+
+ static HInstruction* NewHDiv(Zone* zone,
+ HValue* context,
+ HValue* left,
+ HValue* right);
+
DECLARE_CONCRETE_INSTRUCTION(Div)
protected:
virtual bool IsCommutative() const { return true; }
+ static HInstruction* NewHBitwise(Zone* zone,
+ Token::Value op,
+ HValue* context,
+ HValue* left,
+ HValue* right);
+
DECLARE_CONCRETE_INSTRUCTION(Bitwise)
protected:
virtual Range* InferRange();
+ static HInstruction* NewHShl(Zone* zone,
+ HValue* context,
+ HValue* left,
+ HValue* right);
+
DECLARE_CONCRETE_INSTRUCTION(Shl)
protected:
virtual Range* InferRange();
+ static HInstruction* NewHShr(Zone* zone,
+ HValue* context,
+ HValue* left,
+ HValue* right);
+
DECLARE_CONCRETE_INSTRUCTION(Shr)
protected:
virtual Range* InferRange();
+ static HInstruction* NewHSar(Zone* zone,
+ HValue* context,
+ HValue* left,
+ HValue* right);
+
DECLARE_CONCRETE_INSTRUCTION(Sar)
protected:
AddInstruction(HCheckInstanceType::NewIsString(right));
instr = new(zone()) HStringAdd(context, left, right);
} else {
- instr = new(zone()) HAdd(context, left, right);
+ instr = HAdd::NewHAdd(zone(), context, left, right);
}
break;
case Token::SUB:
- instr = new(zone()) HSub(context, left, right);
+ instr = HSub::NewHSub(zone(), context, left, right);
break;
case Token::MUL:
- instr = new(zone()) HMul(context, left, right);
+ instr = HMul::NewHMul(zone(), context, left, right);
break;
case Token::MOD:
- instr = new(zone()) HMod(context, left, right);
+ instr = HMod::NewHMod(zone(), context, left, right);
break;
case Token::DIV:
- instr = new(zone()) HDiv(context, left, right);
+ instr = HDiv::NewHDiv(zone(), context, left, right);
break;
case Token::BIT_XOR:
case Token::BIT_AND:
case Token::BIT_OR:
- instr = new(zone()) HBitwise(expr->op(), context, left, right);
+ instr = HBitwise::NewHBitwise(zone(), expr->op(), context, left, right);
break;
case Token::SAR:
- instr = new(zone()) HSar(context, left, right);
+ instr = HSar::NewHSar(zone(), context, left, right);
break;
case Token::SHR:
- instr = new(zone()) HShr(context, left, right);
+ instr = HShr::NewHShr(zone(), context, left, right);
break;
case Token::SHL:
- instr = new(zone()) HShl(context, left, right);
+ instr = HShl::NewHShl(zone(), context, left, right);
break;
default:
UNREACHABLE();