Commit 76ac8bc7 authored by lrn@chromium.org's avatar lrn@chromium.org

Removed static type inference and add a dynamic test for string addition.

The complexity of static type inference never really paid off, and as an
analysis it didn't fit well with codegen frame propagation.

Review URL: http://codereview.chromium.org/146077


git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2262 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 1f5a9053
......@@ -359,14 +359,14 @@ class VirtualFrame : public ZoneObject {
void EmitPush(Register reg);
// Push an element on the virtual frame.
void Push(Register reg, StaticType static_type = StaticType());
void Push(Register reg);
void Push(Handle<Object> value);
void Push(Smi* value) { Push(Handle<Object>(value)); }
// Pushing a result invalidates it (its contents become owned by the frame).
void Push(Result* result) {
if (result->is_register()) {
Push(result->reg(), result->static_type());
Push(result->reg());
} else {
ASSERT(result->is_constant());
Push(result->handle());
......
......@@ -54,8 +54,7 @@ class FrameElement BASE_EMBEDDED {
// The default constructor creates an invalid frame element.
FrameElement() {
value_ = StaticTypeField::encode(StaticType::UNKNOWN_TYPE)
| TypeField::encode(INVALID)
value_ = TypeField::encode(INVALID)
| CopiedField::encode(false)
| SyncedField::encode(false)
| DataField::encode(0);
......@@ -75,9 +74,8 @@ class FrameElement BASE_EMBEDDED {
// Factory function to construct an in-register frame element.
static FrameElement RegisterElement(Register reg,
SyncFlag is_synced,
StaticType static_type = StaticType()) {
return FrameElement(REGISTER, reg, is_synced, static_type);
SyncFlag is_synced) {
return FrameElement(REGISTER, reg, is_synced);
}
// Factory function to construct a frame element whose value is known at
......@@ -143,15 +141,6 @@ class FrameElement BASE_EMBEDDED {
return DataField::decode(value_);
}
StaticType static_type() {
return StaticType(StaticTypeField::decode(value_));
}
void set_static_type(StaticType static_type) {
value_ = value_ & ~StaticTypeField::mask();
value_ = value_ | StaticTypeField::encode(static_type.static_type_);
}
bool Equals(FrameElement other) {
uint32_t masked_difference = (value_ ^ other.value_) & ~CopiedField::mask();
if (!masked_difference) {
......@@ -184,13 +173,8 @@ class FrameElement BASE_EMBEDDED {
if (!other->is_valid()) return other;
if (!SameLocation(other)) return NULL;
// If either is unsynced, the result is. The result static type is
// the merge of the static types. It's safe to set it on one of the
// frame elements, and harmless too (because we are only going to
// merge the reaching frames and will ensure that the types are
// coherent, and changing the static type does not emit code).
// If either is unsynced, the result is.
FrameElement* result = is_synced() ? other : this;
result->set_static_type(static_type().merge(other->static_type()));
return result;
}
......@@ -205,16 +189,7 @@ class FrameElement BASE_EMBEDDED {
// Used to construct memory and register elements.
FrameElement(Type type, Register reg, SyncFlag is_synced) {
value_ = StaticTypeField::encode(StaticType::UNKNOWN_TYPE)
| TypeField::encode(type)
| CopiedField::encode(false)
| SyncedField::encode(is_synced != NOT_SYNCED)
| DataField::encode(reg.code_ > 0 ? reg.code_ : 0);
}
FrameElement(Type type, Register reg, SyncFlag is_synced, StaticType stype) {
value_ = StaticTypeField::encode(stype.static_type_)
| TypeField::encode(type)
value_ = TypeField::encode(type)
| CopiedField::encode(false)
| SyncedField::encode(is_synced != NOT_SYNCED)
| DataField::encode(reg.code_ > 0 ? reg.code_ : 0);
......@@ -222,8 +197,7 @@ class FrameElement BASE_EMBEDDED {
// Used to construct constant elements.
FrameElement(Handle<Object> value, SyncFlag is_synced) {
value_ = StaticTypeField::encode(StaticType::TypeOf(*value).static_type_)
| TypeField::encode(CONSTANT)
value_ = TypeField::encode(CONSTANT)
| CopiedField::encode(false)
| SyncedField::encode(is_synced != NOT_SYNCED)
| DataField::encode(ConstantList()->length());
......@@ -248,14 +222,13 @@ class FrameElement BASE_EMBEDDED {
value_ = value_ | DataField::encode(new_reg.code_);
}
// Encode static type, type, copied, synced and data in one 32 bit integer.
// Encode type, copied, synced and data in one 32 bit integer.
uint32_t value_;
class StaticTypeField: public BitField<StaticType::StaticTypeEnum, 0, 3> {};
class TypeField: public BitField<Type, 3, 3> {};
class CopiedField: public BitField<uint32_t, 6, 1> {};
class SyncedField: public BitField<uint32_t, 7, 1> {};
class DataField: public BitField<uint32_t, 8, 32 - 9> {};
class TypeField: public BitField<Type, 0, 3> {};
class CopiedField: public BitField<uint32_t, 3, 1> {};
class SyncedField: public BitField<uint32_t, 4, 1> {};
class DataField: public BitField<uint32_t, 5, 32 - 6> {};
friend class VirtualFrame;
};
......
......@@ -919,15 +919,15 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
Result left = frame_->Pop();
if (op == Token::ADD) {
bool left_is_string = left.static_type().is_jsstring();
bool right_is_string = right.static_type().is_jsstring();
bool left_is_string = left.is_constant() && left.handle()->IsString();
bool right_is_string = right.is_constant() && right.handle()->IsString();
if (left_is_string || right_is_string) {
frame_->Push(&left);
frame_->Push(&right);
Result answer;
if (left_is_string) {
if (right_is_string) {
// TODO(lrn): if (left.is_constant() && right.is_constant())
// TODO(lrn): if both are constant strings
// -- do a compile time cons, if allocation during codegen is allowed.
answer = frame_->CallRuntime(Runtime::kStringAdd, 2);
} else {
......@@ -938,7 +938,6 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
answer =
frame_->InvokeBuiltin(Builtins::STRING_ADD_RIGHT, CALL_FUNCTION, 2);
}
answer.set_static_type(StaticType::jsstring());
frame_->Push(&answer);
return;
}
......@@ -6854,9 +6853,45 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
// result.
__ bind(&call_runtime);
switch (op_) {
case Token::ADD:
case Token::ADD: {
// Test for string arguments before calling runtime.
Label not_strings, both_strings, not_string1, string1;
Result answer;
__ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument.
__ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument.
__ test(eax, Immediate(kSmiTagMask));
__ j(zero, &not_string1);
__ CmpObjectType(eax, FIRST_NONSTRING_TYPE, eax);
__ j(above_equal, &not_string1);
// First argument is a a string, test second.
__ test(edx, Immediate(kSmiTagMask));
__ j(zero, &string1);
__ CmpObjectType(edx, FIRST_NONSTRING_TYPE, edx);
__ j(above_equal, &string1);
// First and second argument are strings.
__ TailCallRuntime(ExternalReference(Runtime::kStringAdd), 2);
// Only first argument is a string.
__ bind(&string1);
__ InvokeBuiltin(Builtins::STRING_ADD_LEFT, JUMP_FUNCTION);
// First argument was not a string, test second.
__ bind(&not_string1);
__ test(edx, Immediate(kSmiTagMask));
__ j(zero, &not_strings);
__ CmpObjectType(edx, FIRST_NONSTRING_TYPE, edx);
__ j(above_equal, &not_strings);
// Only second argument is a string.
__ InvokeBuiltin(Builtins::STRING_ADD_RIGHT, JUMP_FUNCTION);
__ bind(&not_strings);
// Neither argument is a string.
__ InvokeBuiltin(Builtins::ADD, JUMP_FUNCTION);
break;
}
case Token::SUB:
__ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION);
break;
......
......@@ -218,10 +218,7 @@ void VirtualFrame::MakeMergable() {
}
}
}
// No need to set the copied flag---there are no copies.
// Backwards jump targets can never know the type of a value.
elements_[i].set_static_type(StaticType::unknown());
// No need to set the copied flag --- there are no copies.
} else {
// Clear the copy flag of non-constant, non-copy elements.
// They cannot be copied because copies are not allowed.
......@@ -999,7 +996,6 @@ Result VirtualFrame::Pop() {
if (element.is_memory()) {
Result temp = cgen()->allocator()->Allocate();
ASSERT(temp.is_valid());
temp.set_static_type(element.static_type());
__ pop(temp.reg());
return temp;
}
......@@ -1031,12 +1027,11 @@ Result VirtualFrame::Pop() {
FrameElement::RegisterElement(temp.reg(), FrameElement::SYNCED);
// Preserve the copy flag on the element.
if (element.is_copied()) new_element.set_copied();
new_element.set_static_type(element.static_type());
elements_[index] = new_element;
__ mov(temp.reg(), Operand(ebp, fp_relative(index)));
return Result(temp.reg(), element.static_type());
return Result(temp.reg());
} else if (element.is_register()) {
return Result(element.reg(), element.static_type());
return Result(element.reg());
} else {
ASSERT(element.is_constant());
return Result(element.handle());
......
......@@ -43,7 +43,7 @@ namespace internal {
// as random access to the expression stack elements, locals, and
// parameters.
class VirtualFrame : public ZoneObject {
class VirtualFrame: public ZoneObject {
public:
// A utility class to introduce a scope where the virtual frame is
// expected to remain spilled. The constructor spills the code
......@@ -65,7 +65,7 @@ class VirtualFrame : public ZoneObject {
private:
bool previous_state_;
CodeGenerator* cgen() { return CodeGeneratorScope::Current(); }
CodeGenerator* cgen() {return CodeGeneratorScope::Current();}
};
// An illegal index into the virtual frame.
......@@ -78,6 +78,7 @@ class VirtualFrame : public ZoneObject {
explicit VirtualFrame(VirtualFrame* original);
CodeGenerator* cgen() { return CodeGeneratorScope::Current(); }
MacroAssembler* masm() { return cgen()->masm(); }
// Create a duplicate of an existing valid frame element.
......@@ -87,9 +88,7 @@ class VirtualFrame : public ZoneObject {
int element_count() { return elements_.length(); }
// The height of the virtual expression stack.
int height() {
return element_count() - expression_base_index();
}
int height() { return element_count() - expression_base_index(); }
int register_location(int num) {
ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters);
......@@ -255,7 +254,9 @@ class VirtualFrame : public ZoneObject {
void PushReceiverSlotAddress();
// Push the function on top of the frame.
void PushFunction() { PushFrameSlotAt(function_index()); }
void PushFunction() {
PushFrameSlotAt(function_index());
}
// Save the value of the esi register to the context frame slot.
void SaveContextRegister();
......@@ -290,7 +291,9 @@ class VirtualFrame : public ZoneObject {
}
// The receiver frame slot.
Operand Receiver() { return ParameterAt(-1); }
Operand Receiver() {
return ParameterAt(-1);
}
// Push a try-catch or try-finally handler on top of the virtual frame.
void PushTryHandler(HandlerType type);
......@@ -320,9 +323,7 @@ class VirtualFrame : public ZoneObject {
// Invoke builtin given the number of arguments it expects on (and
// removes from) the stack.
Result InvokeBuiltin(Builtins::JavaScript id,
InvokeFlag flag,
int arg_count);
Result InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag, int arg_count);
// Call load IC. Name and receiver are found on top of the frame.
// Receiver is not dropped.
......@@ -357,10 +358,14 @@ class VirtualFrame : public ZoneObject {
void Drop(int count);
// Drop one element.
void Drop() { Drop(1); }
void Drop() {
Drop(1);
}
// Duplicate the top element of the frame.
void Dup() { PushFrameSlotAt(element_count() - 1); }
void Dup() {
PushFrameSlotAt(element_count() - 1);
}
// Pop an element from the top of the expression stack. Returns a
// Result, which may be a constant or a register.
......@@ -378,15 +383,17 @@ class VirtualFrame : public ZoneObject {
void EmitPush(Immediate immediate);
// Push an element on the virtual frame.
void Push(Register reg, StaticType static_type = StaticType());
void Push(Register reg);
void Push(Handle<Object> value);
void Push(Smi* value) { Push(Handle<Object>(value)); }
void Push(Smi* value) {
Push(Handle<Object> (value));
}
// Pushing a result invalidates it (its contents become owned by the
// frame).
void Push(Result* result) {
if (result->is_register()) {
Push(result->reg(), result->static_type());
Push(result->reg());
} else {
ASSERT(result->is_constant());
Push(result->handle());
......@@ -418,32 +425,48 @@ class VirtualFrame : public ZoneObject {
int register_locations_[RegisterAllocator::kNumRegisters];
// The number of frame-allocated locals and parameters respectively.
int parameter_count() { return cgen()->scope()->num_parameters(); }
int local_count() { return cgen()->scope()->num_stack_slots(); }
int parameter_count() {
return cgen()->scope()->num_parameters();
}
int local_count() {
return cgen()->scope()->num_stack_slots();
}
// The index of the element that is at the processor's frame pointer
// (the ebp register). The parameters, receiver, and return address
// are below the frame pointer.
int frame_pointer() { return parameter_count() + 2; }
int frame_pointer() {
return parameter_count() + 2;
}
// The index of the first parameter. The receiver lies below the first
// parameter.
int param0_index() { return 1; }
int param0_index() {
return 1;
}
// The index of the context slot in the frame. It is immediately
// above the frame pointer.
int context_index() { return frame_pointer() + 1; }
int context_index() {
return frame_pointer() + 1;
}
// The index of the function slot in the frame. It is above the frame
// pointer and the context slot.
int function_index() { return frame_pointer() + 2; }
int function_index() {
return frame_pointer() + 2;
}
// The index of the first local. Between the frame pointer and the
// locals lie the context and the function.
int local0_index() { return frame_pointer() + 3; }
int local0_index() {
return frame_pointer() + 3;
}
// The index of the base of the expression stack.
int expression_base_index() { return local0_index() + local_count(); }
int expression_base_index() {
return local0_index() + local_count();
}
// Convert a frame index into a frame pointer relative offset into the
// actual stack.
......@@ -547,7 +570,6 @@ class VirtualFrame : public ZoneObject {
friend class JumpTarget;
};
} } // namespace v8::internal
#endif // V8_IA32_VIRTUAL_FRAME_IA32_H_
......@@ -81,17 +81,12 @@ void JumpTarget::ComputeEntryFrame() {
// frame.
for (int i = 0; i < length; i++) {
FrameElement element = initial_frame->elements_[i];
// We do not allow copies or constants in bidirectional frames. All
// elements above the water mark on bidirectional frames have
// unknown static types.
// We do not allow copies or constants in bidirectional frames.
if (direction_ == BIDIRECTIONAL) {
if (element.is_constant() || element.is_copy()) {
elements.Add(NULL);
continue;
}
// It's safe to change the static type on the initial frame
// element, see comment in JumpTarget::Combine.
initial_frame->elements_[i].set_static_type(StaticType::unknown());
}
elements.Add(&initial_frame->elements_[i]);
}
......@@ -142,18 +137,12 @@ void JumpTarget::ComputeEntryFrame() {
for (int i = length - 1; i >= 0; i--) {
if (elements[i] == NULL) {
// Loop over all the reaching frames to check whether the element
// is synced on all frames, to count the registers it occupies,
// and to compute a merged static type.
// is synced on all frames and to count the registers it occupies.
bool is_synced = true;
RegisterFile candidate_registers;
int best_count = kMinInt;
int best_reg_num = RegisterAllocator::kInvalidRegister;
StaticType type; // Initially invalid.
if (direction_ != BIDIRECTIONAL) {
type = reaching_frames_[0]->elements_[i].static_type();
}
for (int j = 0; j < reaching_frames_.length(); j++) {
FrameElement element = reaching_frames_[j]->elements_[i];
is_synced = is_synced && element.is_synced();
......@@ -167,7 +156,6 @@ void JumpTarget::ComputeEntryFrame() {
best_reg_num = num;
}
}
type = type.merge(element.static_type());
}
// If the value is synced on all frames, put it in memory. This
......@@ -175,7 +163,6 @@ void JumpTarget::ComputeEntryFrame() {
// memory-to-register move when the value is needed later.
if (is_synced) {
// Already recorded as a memory element.
entry_frame_->elements_[i].set_static_type(type);
continue;
}
......@@ -190,20 +177,15 @@ void JumpTarget::ComputeEntryFrame() {
}
}
if (best_reg_num == RegisterAllocator::kInvalidRegister) {
// If there was no register found, the element is already
// recorded as in memory.
entry_frame_->elements_[i].set_static_type(type);
} else {
if (best_reg_num != RegisterAllocator::kInvalidRegister) {
// If there was a register choice, use it. Preserve the copied
// flag on the element. Set the static type as computed.
// flag on the element.
bool is_copied = entry_frame_->elements_[i].is_copied();
Register reg = RegisterAllocator::ToRegister(best_reg_num);
entry_frame_->elements_[i] =
FrameElement::RegisterElement(reg,
FrameElement::NOT_SYNCED);
if (is_copied) entry_frame_->elements_[i].set_copied();
entry_frame_->elements_[i].set_static_type(type);
entry_frame_->set_register_location(reg, i);
}
}
......
......@@ -40,18 +40,7 @@ namespace internal {
Result::Result(Register reg) {
ASSERT(reg.is_valid() && !RegisterAllocator::IsReserved(reg));
CodeGeneratorScope::Current()->allocator()->Use(reg);
value_ = StaticTypeField::encode(StaticType::UNKNOWN_TYPE)
| TypeField::encode(REGISTER)
| DataField::encode(reg.code_);
}
Result::Result(Register reg, StaticType type) {
ASSERT(reg.is_valid() && !RegisterAllocator::IsReserved(reg));
CodeGeneratorScope::Current()->allocator()->Use(reg);
value_ = StaticTypeField::encode(type.static_type_)
| TypeField::encode(REGISTER)
| DataField::encode(reg.code_);
value_ = TypeField::encode(REGISTER) | DataField::encode(reg.code_);
}
......
......@@ -44,80 +44,6 @@ namespace v8 {
namespace internal {
// -------------------------------------------------------------------------
// StaticType
//
// StaticType represent the type of an expression or a word at runtime.
// The types are ordered by knowledge, so that if a value can come about
// in more than one way, and there are different static types inferred
// for the different ways, the types can be combined to a type that we
// are still certain of (possibly just "unknown").
class StaticType BASE_EMBEDDED {
public:
StaticType() : static_type_(UNKNOWN_TYPE) {}
static StaticType unknown() { return StaticType(); }
static StaticType smi() { return StaticType(SMI_TYPE); }
static StaticType jsstring() { return StaticType(STRING_TYPE); }
static StaticType heap_object() { return StaticType(HEAP_OBJECT_TYPE); }
// Accessors
bool is_unknown() { return static_type_ == UNKNOWN_TYPE; }
bool is_smi() { return static_type_ == SMI_TYPE; }
bool is_heap_object() { return (static_type_ & HEAP_OBJECT_TYPE) != 0; }
bool is_jsstring() { return static_type_ == STRING_TYPE; }
bool operator==(StaticType other) const {
return static_type_ == other.static_type_;
}
// Find the best approximating type for a value.
// The argument must not be NULL.
static StaticType TypeOf(Object* object) {
// Remember to make the most specific tests first. A string is also a heap
// object, so test for string-ness first.
if (object->IsSmi()) return smi();
if (object->IsString()) return jsstring();
if (object->IsHeapObject()) return heap_object();
return unknown();
}
// Merges two static types to a type that combines the knowledge
// of both. If there is no way to combine (e.g., being a string *and*
// being a smi), the resulting type is unknown.
StaticType merge(StaticType other) {
StaticType x(
static_cast<StaticTypeEnum>(static_type_ & other.static_type_));
return x;
}
private:
enum StaticTypeEnum {
// Numbers are chosen so that least upper bound of the following
// partial order is implemented by bitwise "and":
//
// string
// |
// heap-object smi
// \ /
// unknown
//
UNKNOWN_TYPE = 0x00,
SMI_TYPE = 0x01,
HEAP_OBJECT_TYPE = 0x02,
STRING_TYPE = 0x04 | HEAP_OBJECT_TYPE
};
explicit StaticType(StaticTypeEnum static_type) : static_type_(static_type) {}
// StaticTypeEnum static_type_;
StaticTypeEnum static_type_;
friend class FrameElement;
friend class Result;
};
// -------------------------------------------------------------------------
// Results
//
......@@ -138,13 +64,9 @@ class Result BASE_EMBEDDED {
// Construct a register Result.
explicit Result(Register reg);
// Construct a register Result with a known static type.
Result(Register reg, StaticType static_type);
// Construct a Result whose value is a compile-time constant.
explicit Result(Handle<Object> value) {
value_ = StaticTypeField::encode(StaticType::TypeOf(*value).static_type_)
| TypeField::encode(CONSTANT)
value_ = TypeField::encode(CONSTANT)
| DataField::encode(ConstantList()->length());
ConstantList()->Add(value);
}
......@@ -182,15 +104,6 @@ class Result BASE_EMBEDDED {
inline void Unuse();
StaticType static_type() const {
return StaticType(StaticTypeField::decode(value_));
}
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); }
......@@ -225,9 +138,8 @@ class Result BASE_EMBEDDED {
private:
uint32_t value_;
class StaticTypeField: public BitField<StaticType::StaticTypeEnum, 0, 3> {};
class TypeField: public BitField<Type, 3, 2> {};
class DataField: public BitField<uint32_t, 5, 32 - 6> {};
class TypeField: public BitField<Type, 0, 2> {};
class DataField: public BitField<uint32_t, 2, 32 - 3> {};
inline void CopyTo(Result* destination) const;
......
......@@ -73,7 +73,6 @@ FrameElement VirtualFrame::CopyElementAt(int index) {
case FrameElement::MEMORY: // Fall through.
case FrameElement::REGISTER:
// All copies are backed by memory or register locations.
result.set_static_type(target.static_type());
result.set_type(FrameElement::COPY);
result.clear_copied();
result.clear_sync();
......@@ -153,7 +152,6 @@ void VirtualFrame::SpillElementAt(int index) {
if (elements_[index].is_register()) {
Unuse(elements_[index].reg());
}
new_element.set_static_type(elements_[index].static_type());
elements_[index] = new_element;
}
......@@ -211,9 +209,6 @@ void VirtualFrame::PrepareMergeTo(VirtualFrame* expected) {
ASSERT(source.is_valid());
elements_[i].clear_sync();
}
// No code needs to be generated to change the static type of an
// element.
elements_[i].set_static_type(target.static_type());
}
}
......@@ -246,11 +241,8 @@ void VirtualFrame::PrepareForCall(int spilled_args, int dropped_args) {
void VirtualFrame::PrepareForReturn() {
// Spill all locals. This is necessary to make sure all locals have
// the right value when breaking at the return site in the debugger.
// Set their static type to unknown so that they will match the known
// return frame.
for (int i = 0; i < expression_base_index(); i++) {
SpillElementAt(i);
elements_[i].set_static_type(StaticType::unknown());
}
}
......@@ -283,7 +275,6 @@ void VirtualFrame::SetElementAt(int index, Result* value) {
// register element, or the new element at frame_index, must be made
// a copy.
int i = register_location(value->reg());
ASSERT(value->static_type() == elements_[i].static_type());
if (i < frame_index) {
// The register FrameElement is lower in the frame than the new copy.
......@@ -310,8 +301,7 @@ void VirtualFrame::SetElementAt(int index, Result* value) {
Use(value->reg(), frame_index);
elements_[frame_index] =
FrameElement::RegisterElement(value->reg(),
FrameElement::NOT_SYNCED,
value->static_type());
FrameElement::NOT_SYNCED);
}
} else {
ASSERT(value->is_constant());
......@@ -328,18 +318,16 @@ void VirtualFrame::PushFrameSlotAt(int index) {
}
void VirtualFrame::Push(Register reg, StaticType static_type) {
void VirtualFrame::Push(Register reg) {
if (is_used(reg)) {
int index = register_location(reg);
FrameElement element = CopyElementAt(index);
ASSERT(static_type.merge(element.static_type()) == element.static_type());
elements_.Add(element);
} else {
Use(reg, element_count());
FrameElement element =
FrameElement::RegisterElement(reg,
FrameElement::NOT_SYNCED,
static_type);
FrameElement::NOT_SYNCED);
elements_.Add(element);
}
}
......
......@@ -2368,15 +2368,15 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
Result left = frame_->Pop();
if (op == Token::ADD) {
bool left_is_string = left.static_type().is_jsstring();
bool right_is_string = right.static_type().is_jsstring();
bool left_is_string = left.is_constant() && left.handle()->IsString();
bool right_is_string = right.is_constant() && right.handle()->IsString();
if (left_is_string || right_is_string) {
frame_->Push(&left);
frame_->Push(&right);
Result answer;
if (left_is_string) {
if (right_is_string) {
// TODO(lrn): if (left.is_constant() && right.is_constant())
// TODO(lrn): if both are constant strings
// -- do a compile time cons, if allocation during codegen is allowed.
answer = frame_->CallRuntime(Runtime::kStringAdd, 2);
} else {
......@@ -2387,7 +2387,6 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
answer =
frame_->InvokeBuiltin(Builtins::STRING_ADD_RIGHT, CALL_FUNCTION, 2);
}
answer.set_static_type(StaticType::jsstring());
frame_->Push(&answer);
return;
}
......
......@@ -432,8 +432,7 @@ void VirtualFrame::MakeMergable() {
}
}
}
// No need to set the copied flag---there are no copies.
elements_[i].set_static_type(StaticType::unknown());
// No need to set the copied flag --- there are no copies.
} else {
// Clear the copy flag of non-constant, non-copy elements.
// They cannot be copied because copies are not allowed.
......@@ -651,7 +650,6 @@ Result VirtualFrame::Pop() {
if (element.is_memory()) {
Result temp = cgen()->allocator()->Allocate();
ASSERT(temp.is_valid());
temp.set_static_type(element.static_type());
__ pop(temp.reg());
return temp;
}
......@@ -683,12 +681,11 @@ Result VirtualFrame::Pop() {
FrameElement::RegisterElement(temp.reg(), FrameElement::SYNCED);
// Preserve the copy flag on the element.
if (element.is_copied()) new_element.set_copied();
new_element.set_static_type(element.static_type());
elements_[index] = new_element;
__ movq(temp.reg(), Operand(rbp, fp_relative(index)));
return Result(temp.reg(), element.static_type());
return Result(temp.reg());
} else if (element.is_register()) {
return Result(element.reg(), element.static_type());
return Result(element.reg());
} else {
ASSERT(element.is_constant());
return Result(element.handle());
......
......@@ -378,7 +378,7 @@ class VirtualFrame : public ZoneObject {
void EmitPush(Immediate immediate);
// Push an element on the virtual frame.
void Push(Register reg, StaticType static_type = StaticType());
void Push(Register reg);
void Push(Handle<Object> value);
void Push(Smi* value) { Push(Handle<Object>(value)); }
......@@ -386,7 +386,7 @@ class VirtualFrame : public ZoneObject {
// frame).
void Push(Result* result) {
if (result->is_register()) {
Push(result->reg(), result->static_type());
Push(result->reg());
} else {
ASSERT(result->is_constant());
Push(result->handle());
......
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