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 { ...@@ -359,14 +359,14 @@ class VirtualFrame : public ZoneObject {
void EmitPush(Register reg); void EmitPush(Register reg);
// Push an element on the virtual frame. // 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(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). // Pushing a result invalidates it (its contents become owned by the frame).
void Push(Result* result) { void Push(Result* result) {
if (result->is_register()) { if (result->is_register()) {
Push(result->reg(), result->static_type()); Push(result->reg());
} else { } else {
ASSERT(result->is_constant()); ASSERT(result->is_constant());
Push(result->handle()); Push(result->handle());
......
...@@ -54,8 +54,7 @@ class FrameElement BASE_EMBEDDED { ...@@ -54,8 +54,7 @@ class FrameElement BASE_EMBEDDED {
// The default constructor creates an invalid frame element. // The default constructor creates an invalid frame element.
FrameElement() { FrameElement() {
value_ = StaticTypeField::encode(StaticType::UNKNOWN_TYPE) value_ = TypeField::encode(INVALID)
| TypeField::encode(INVALID)
| CopiedField::encode(false) | CopiedField::encode(false)
| SyncedField::encode(false) | SyncedField::encode(false)
| DataField::encode(0); | DataField::encode(0);
...@@ -75,9 +74,8 @@ class FrameElement BASE_EMBEDDED { ...@@ -75,9 +74,8 @@ class FrameElement BASE_EMBEDDED {
// Factory function to construct an in-register frame element. // Factory function to construct an in-register frame element.
static FrameElement RegisterElement(Register reg, static FrameElement RegisterElement(Register reg,
SyncFlag is_synced, SyncFlag is_synced) {
StaticType static_type = StaticType()) { return FrameElement(REGISTER, reg, is_synced);
return FrameElement(REGISTER, reg, is_synced, static_type);
} }
// Factory function to construct a frame element whose value is known at // Factory function to construct a frame element whose value is known at
...@@ -143,15 +141,6 @@ class FrameElement BASE_EMBEDDED { ...@@ -143,15 +141,6 @@ class FrameElement BASE_EMBEDDED {
return DataField::decode(value_); 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) { bool Equals(FrameElement other) {
uint32_t masked_difference = (value_ ^ other.value_) & ~CopiedField::mask(); uint32_t masked_difference = (value_ ^ other.value_) & ~CopiedField::mask();
if (!masked_difference) { if (!masked_difference) {
...@@ -184,13 +173,8 @@ class FrameElement BASE_EMBEDDED { ...@@ -184,13 +173,8 @@ class FrameElement BASE_EMBEDDED {
if (!other->is_valid()) return other; if (!other->is_valid()) return other;
if (!SameLocation(other)) return NULL; if (!SameLocation(other)) return NULL;
// If either is unsynced, the result is. The result static type is // If either is unsynced, the result 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).
FrameElement* result = is_synced() ? other : this; FrameElement* result = is_synced() ? other : this;
result->set_static_type(static_type().merge(other->static_type()));
return result; return result;
} }
...@@ -205,16 +189,7 @@ class FrameElement BASE_EMBEDDED { ...@@ -205,16 +189,7 @@ class FrameElement BASE_EMBEDDED {
// Used to construct memory and register elements. // Used to construct memory and register elements.
FrameElement(Type type, Register reg, SyncFlag is_synced) { FrameElement(Type type, Register reg, SyncFlag is_synced) {
value_ = StaticTypeField::encode(StaticType::UNKNOWN_TYPE) value_ = TypeField::encode(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)
| CopiedField::encode(false) | CopiedField::encode(false)
| SyncedField::encode(is_synced != NOT_SYNCED) | SyncedField::encode(is_synced != NOT_SYNCED)
| DataField::encode(reg.code_ > 0 ? reg.code_ : 0); | DataField::encode(reg.code_ > 0 ? reg.code_ : 0);
...@@ -222,8 +197,7 @@ class FrameElement BASE_EMBEDDED { ...@@ -222,8 +197,7 @@ class FrameElement BASE_EMBEDDED {
// Used to construct constant elements. // Used to construct constant elements.
FrameElement(Handle<Object> value, SyncFlag is_synced) { FrameElement(Handle<Object> value, SyncFlag is_synced) {
value_ = StaticTypeField::encode(StaticType::TypeOf(*value).static_type_) value_ = TypeField::encode(CONSTANT)
| TypeField::encode(CONSTANT)
| CopiedField::encode(false) | CopiedField::encode(false)
| SyncedField::encode(is_synced != NOT_SYNCED) | SyncedField::encode(is_synced != NOT_SYNCED)
| DataField::encode(ConstantList()->length()); | DataField::encode(ConstantList()->length());
...@@ -248,14 +222,13 @@ class FrameElement BASE_EMBEDDED { ...@@ -248,14 +222,13 @@ class FrameElement BASE_EMBEDDED {
value_ = value_ | DataField::encode(new_reg.code_); 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_; uint32_t value_;
class StaticTypeField: public BitField<StaticType::StaticTypeEnum, 0, 3> {}; class TypeField: public BitField<Type, 0, 3> {};
class TypeField: public BitField<Type, 3, 3> {}; class CopiedField: public BitField<uint32_t, 3, 1> {};
class CopiedField: public BitField<uint32_t, 6, 1> {}; class SyncedField: public BitField<uint32_t, 4, 1> {};
class SyncedField: public BitField<uint32_t, 7, 1> {}; class DataField: public BitField<uint32_t, 5, 32 - 6> {};
class DataField: public BitField<uint32_t, 8, 32 - 9> {};
friend class VirtualFrame; friend class VirtualFrame;
}; };
......
...@@ -919,15 +919,15 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op, ...@@ -919,15 +919,15 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
Result left = frame_->Pop(); Result left = frame_->Pop();
if (op == Token::ADD) { if (op == Token::ADD) {
bool left_is_string = left.static_type().is_jsstring(); bool left_is_string = left.is_constant() && left.handle()->IsString();
bool right_is_string = right.static_type().is_jsstring(); bool right_is_string = right.is_constant() && right.handle()->IsString();
if (left_is_string || right_is_string) { if (left_is_string || right_is_string) {
frame_->Push(&left); frame_->Push(&left);
frame_->Push(&right); frame_->Push(&right);
Result answer; Result answer;
if (left_is_string) { if (left_is_string) {
if (right_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. // -- do a compile time cons, if allocation during codegen is allowed.
answer = frame_->CallRuntime(Runtime::kStringAdd, 2); answer = frame_->CallRuntime(Runtime::kStringAdd, 2);
} else { } else {
...@@ -938,7 +938,6 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op, ...@@ -938,7 +938,6 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
answer = answer =
frame_->InvokeBuiltin(Builtins::STRING_ADD_RIGHT, CALL_FUNCTION, 2); frame_->InvokeBuiltin(Builtins::STRING_ADD_RIGHT, CALL_FUNCTION, 2);
} }
answer.set_static_type(StaticType::jsstring());
frame_->Push(&answer); frame_->Push(&answer);
return; return;
} }
...@@ -6854,9 +6853,45 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) { ...@@ -6854,9 +6853,45 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
// result. // result.
__ bind(&call_runtime); __ bind(&call_runtime);
switch (op_) { 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); __ InvokeBuiltin(Builtins::ADD, JUMP_FUNCTION);
break; break;
}
case Token::SUB: case Token::SUB:
__ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION); __ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION);
break; break;
......
...@@ -218,10 +218,7 @@ void VirtualFrame::MakeMergable() { ...@@ -218,10 +218,7 @@ void VirtualFrame::MakeMergable() {
} }
} }
} }
// No need to set the copied flag---there are no copies. // 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());
} else { } else {
// Clear the copy flag of non-constant, non-copy elements. // Clear the copy flag of non-constant, non-copy elements.
// They cannot be copied because copies are not allowed. // They cannot be copied because copies are not allowed.
...@@ -999,7 +996,6 @@ Result VirtualFrame::Pop() { ...@@ -999,7 +996,6 @@ Result VirtualFrame::Pop() {
if (element.is_memory()) { if (element.is_memory()) {
Result temp = cgen()->allocator()->Allocate(); Result temp = cgen()->allocator()->Allocate();
ASSERT(temp.is_valid()); ASSERT(temp.is_valid());
temp.set_static_type(element.static_type());
__ pop(temp.reg()); __ pop(temp.reg());
return temp; return temp;
} }
...@@ -1031,12 +1027,11 @@ Result VirtualFrame::Pop() { ...@@ -1031,12 +1027,11 @@ Result VirtualFrame::Pop() {
FrameElement::RegisterElement(temp.reg(), FrameElement::SYNCED); FrameElement::RegisterElement(temp.reg(), FrameElement::SYNCED);
// Preserve the copy flag on the element. // Preserve the copy flag on the element.
if (element.is_copied()) new_element.set_copied(); if (element.is_copied()) new_element.set_copied();
new_element.set_static_type(element.static_type());
elements_[index] = new_element; elements_[index] = new_element;
__ mov(temp.reg(), Operand(ebp, fp_relative(index))); __ mov(temp.reg(), Operand(ebp, fp_relative(index)));
return Result(temp.reg(), element.static_type()); return Result(temp.reg());
} else if (element.is_register()) { } else if (element.is_register()) {
return Result(element.reg(), element.static_type()); return Result(element.reg());
} else { } else {
ASSERT(element.is_constant()); ASSERT(element.is_constant());
return Result(element.handle()); return Result(element.handle());
......
...@@ -43,7 +43,7 @@ namespace internal { ...@@ -43,7 +43,7 @@ namespace internal {
// as random access to the expression stack elements, locals, and // as random access to the expression stack elements, locals, and
// parameters. // parameters.
class VirtualFrame : public ZoneObject { class VirtualFrame: public ZoneObject {
public: public:
// A utility class to introduce a scope where the virtual frame is // A utility class to introduce a scope where the virtual frame is
// expected to remain spilled. The constructor spills the code // expected to remain spilled. The constructor spills the code
...@@ -65,7 +65,7 @@ class VirtualFrame : public ZoneObject { ...@@ -65,7 +65,7 @@ class VirtualFrame : public ZoneObject {
private: private:
bool previous_state_; bool previous_state_;
CodeGenerator* cgen() { return CodeGeneratorScope::Current(); } CodeGenerator* cgen() {return CodeGeneratorScope::Current();}
}; };
// An illegal index into the virtual frame. // An illegal index into the virtual frame.
...@@ -78,6 +78,7 @@ class VirtualFrame : public ZoneObject { ...@@ -78,6 +78,7 @@ class VirtualFrame : public ZoneObject {
explicit VirtualFrame(VirtualFrame* original); explicit VirtualFrame(VirtualFrame* original);
CodeGenerator* cgen() { return CodeGeneratorScope::Current(); } CodeGenerator* cgen() { return CodeGeneratorScope::Current(); }
MacroAssembler* masm() { return cgen()->masm(); } MacroAssembler* masm() { return cgen()->masm(); }
// Create a duplicate of an existing valid frame element. // Create a duplicate of an existing valid frame element.
...@@ -87,9 +88,7 @@ class VirtualFrame : public ZoneObject { ...@@ -87,9 +88,7 @@ class VirtualFrame : public ZoneObject {
int element_count() { return elements_.length(); } int element_count() { return elements_.length(); }
// The height of the virtual expression stack. // The height of the virtual expression stack.
int height() { int height() { return element_count() - expression_base_index(); }
return element_count() - expression_base_index();
}
int register_location(int num) { int register_location(int num) {
ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters); ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters);
...@@ -255,7 +254,9 @@ class VirtualFrame : public ZoneObject { ...@@ -255,7 +254,9 @@ class VirtualFrame : public ZoneObject {
void PushReceiverSlotAddress(); void PushReceiverSlotAddress();
// Push the function on top of the frame. // 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. // Save the value of the esi register to the context frame slot.
void SaveContextRegister(); void SaveContextRegister();
...@@ -290,7 +291,9 @@ class VirtualFrame : public ZoneObject { ...@@ -290,7 +291,9 @@ class VirtualFrame : public ZoneObject {
} }
// The receiver frame slot. // 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. // Push a try-catch or try-finally handler on top of the virtual frame.
void PushTryHandler(HandlerType type); void PushTryHandler(HandlerType type);
...@@ -320,9 +323,7 @@ class VirtualFrame : public ZoneObject { ...@@ -320,9 +323,7 @@ class VirtualFrame : public ZoneObject {
// Invoke builtin given the number of arguments it expects on (and // Invoke builtin given the number of arguments it expects on (and
// removes from) the stack. // removes from) the stack.
Result InvokeBuiltin(Builtins::JavaScript id, Result InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag, int arg_count);
InvokeFlag flag,
int arg_count);
// Call load IC. Name and receiver are found on top of the frame. // Call load IC. Name and receiver are found on top of the frame.
// Receiver is not dropped. // Receiver is not dropped.
...@@ -357,10 +358,14 @@ class VirtualFrame : public ZoneObject { ...@@ -357,10 +358,14 @@ class VirtualFrame : public ZoneObject {
void Drop(int count); void Drop(int count);
// Drop one element. // Drop one element.
void Drop() { Drop(1); } void Drop() {
Drop(1);
}
// Duplicate the top element of the frame. // 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 // Pop an element from the top of the expression stack. Returns a
// Result, which may be a constant or a register. // Result, which may be a constant or a register.
...@@ -378,15 +383,17 @@ class VirtualFrame : public ZoneObject { ...@@ -378,15 +383,17 @@ class VirtualFrame : public ZoneObject {
void EmitPush(Immediate immediate); void EmitPush(Immediate immediate);
// Push an element on the virtual frame. // 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(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 // Pushing a result invalidates it (its contents become owned by the
// frame). // frame).
void Push(Result* result) { void Push(Result* result) {
if (result->is_register()) { if (result->is_register()) {
Push(result->reg(), result->static_type()); Push(result->reg());
} else { } else {
ASSERT(result->is_constant()); ASSERT(result->is_constant());
Push(result->handle()); Push(result->handle());
...@@ -418,32 +425,48 @@ class VirtualFrame : public ZoneObject { ...@@ -418,32 +425,48 @@ class VirtualFrame : public ZoneObject {
int register_locations_[RegisterAllocator::kNumRegisters]; int register_locations_[RegisterAllocator::kNumRegisters];
// The number of frame-allocated locals and parameters respectively. // The number of frame-allocated locals and parameters respectively.
int parameter_count() { return cgen()->scope()->num_parameters(); } int parameter_count() {
int local_count() { return cgen()->scope()->num_stack_slots(); } 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 index of the element that is at the processor's frame pointer
// (the ebp register). The parameters, receiver, and return address // (the ebp register). The parameters, receiver, and return address
// are below the frame pointer. // 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 // The index of the first parameter. The receiver lies below the first
// parameter. // parameter.
int param0_index() { return 1; } int param0_index() {
return 1;
}
// The index of the context slot in the frame. It is immediately // The index of the context slot in the frame. It is immediately
// above the frame pointer. // 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 // The index of the function slot in the frame. It is above the frame
// pointer and the context slot. // 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 // The index of the first local. Between the frame pointer and the
// locals lie the context and the function. // 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. // 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 // Convert a frame index into a frame pointer relative offset into the
// actual stack. // actual stack.
...@@ -547,7 +570,6 @@ class VirtualFrame : public ZoneObject { ...@@ -547,7 +570,6 @@ class VirtualFrame : public ZoneObject {
friend class JumpTarget; friend class JumpTarget;
}; };
} } // namespace v8::internal } } // namespace v8::internal
#endif // V8_IA32_VIRTUAL_FRAME_IA32_H_ #endif // V8_IA32_VIRTUAL_FRAME_IA32_H_
...@@ -81,17 +81,12 @@ void JumpTarget::ComputeEntryFrame() { ...@@ -81,17 +81,12 @@ void JumpTarget::ComputeEntryFrame() {
// frame. // frame.
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
FrameElement element = initial_frame->elements_[i]; FrameElement element = initial_frame->elements_[i];
// We do not allow copies or constants in bidirectional frames. All // We do not allow copies or constants in bidirectional frames.
// elements above the water mark on bidirectional frames have
// unknown static types.
if (direction_ == BIDIRECTIONAL) { if (direction_ == BIDIRECTIONAL) {
if (element.is_constant() || element.is_copy()) { if (element.is_constant() || element.is_copy()) {
elements.Add(NULL); elements.Add(NULL);
continue; 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]); elements.Add(&initial_frame->elements_[i]);
} }
...@@ -142,18 +137,12 @@ void JumpTarget::ComputeEntryFrame() { ...@@ -142,18 +137,12 @@ void JumpTarget::ComputeEntryFrame() {
for (int i = length - 1; i >= 0; i--) { for (int i = length - 1; i >= 0; i--) {
if (elements[i] == NULL) { if (elements[i] == NULL) {
// Loop over all the reaching frames to check whether the element // Loop over all the reaching frames to check whether the element
// is synced on all frames, to count the registers it occupies, // is synced on all frames and to count the registers it occupies.
// and to compute a merged static type.
bool is_synced = true; bool is_synced = true;
RegisterFile candidate_registers; RegisterFile candidate_registers;
int best_count = kMinInt; int best_count = kMinInt;
int best_reg_num = RegisterAllocator::kInvalidRegister; 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++) { for (int j = 0; j < reaching_frames_.length(); j++) {
FrameElement element = reaching_frames_[j]->elements_[i]; FrameElement element = reaching_frames_[j]->elements_[i];
is_synced = is_synced && element.is_synced(); is_synced = is_synced && element.is_synced();
...@@ -167,7 +156,6 @@ void JumpTarget::ComputeEntryFrame() { ...@@ -167,7 +156,6 @@ void JumpTarget::ComputeEntryFrame() {
best_reg_num = num; best_reg_num = num;
} }
} }
type = type.merge(element.static_type());
} }
// If the value is synced on all frames, put it in memory. This // If the value is synced on all frames, put it in memory. This
...@@ -175,7 +163,6 @@ void JumpTarget::ComputeEntryFrame() { ...@@ -175,7 +163,6 @@ void JumpTarget::ComputeEntryFrame() {
// memory-to-register move when the value is needed later. // memory-to-register move when the value is needed later.
if (is_synced) { if (is_synced) {
// Already recorded as a memory element. // Already recorded as a memory element.
entry_frame_->elements_[i].set_static_type(type);
continue; continue;
} }
...@@ -190,20 +177,15 @@ void JumpTarget::ComputeEntryFrame() { ...@@ -190,20 +177,15 @@ void JumpTarget::ComputeEntryFrame() {
} }
} }
if (best_reg_num == RegisterAllocator::kInvalidRegister) { 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 there was a register choice, use it. Preserve the copied // 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(); bool is_copied = entry_frame_->elements_[i].is_copied();
Register reg = RegisterAllocator::ToRegister(best_reg_num); Register reg = RegisterAllocator::ToRegister(best_reg_num);
entry_frame_->elements_[i] = entry_frame_->elements_[i] =
FrameElement::RegisterElement(reg, FrameElement::RegisterElement(reg,
FrameElement::NOT_SYNCED); FrameElement::NOT_SYNCED);
if (is_copied) entry_frame_->elements_[i].set_copied(); if (is_copied) entry_frame_->elements_[i].set_copied();
entry_frame_->elements_[i].set_static_type(type);
entry_frame_->set_register_location(reg, i); entry_frame_->set_register_location(reg, i);
} }
} }
......
...@@ -40,18 +40,7 @@ namespace internal { ...@@ -40,18 +40,7 @@ namespace internal {
Result::Result(Register reg) { Result::Result(Register reg) {
ASSERT(reg.is_valid() && !RegisterAllocator::IsReserved(reg)); ASSERT(reg.is_valid() && !RegisterAllocator::IsReserved(reg));
CodeGeneratorScope::Current()->allocator()->Use(reg); CodeGeneratorScope::Current()->allocator()->Use(reg);
value_ = StaticTypeField::encode(StaticType::UNKNOWN_TYPE) value_ = TypeField::encode(REGISTER) | DataField::encode(reg.code_);
| 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_);
} }
......
...@@ -44,80 +44,6 @@ namespace v8 { ...@@ -44,80 +44,6 @@ namespace v8 {
namespace internal { 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 // Results
// //
...@@ -138,13 +64,9 @@ class Result BASE_EMBEDDED { ...@@ -138,13 +64,9 @@ class Result BASE_EMBEDDED {
// Construct a register Result. // Construct a register Result.
explicit Result(Register reg); 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. // Construct a Result whose value is a compile-time constant.
explicit Result(Handle<Object> value) { explicit Result(Handle<Object> value) {
value_ = StaticTypeField::encode(StaticType::TypeOf(*value).static_type_) value_ = TypeField::encode(CONSTANT)
| TypeField::encode(CONSTANT)
| DataField::encode(ConstantList()->length()); | DataField::encode(ConstantList()->length());
ConstantList()->Add(value); ConstantList()->Add(value);
} }
...@@ -182,15 +104,6 @@ class Result BASE_EMBEDDED { ...@@ -182,15 +104,6 @@ class Result BASE_EMBEDDED {
inline void Unuse(); 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_); } Type type() const { return TypeField::decode(value_); }
void invalidate() { value_ = TypeField::encode(INVALID); } void invalidate() { value_ = TypeField::encode(INVALID); }
...@@ -225,9 +138,8 @@ class Result BASE_EMBEDDED { ...@@ -225,9 +138,8 @@ class Result BASE_EMBEDDED {
private: private:
uint32_t value_; uint32_t value_;
class StaticTypeField: public BitField<StaticType::StaticTypeEnum, 0, 3> {}; class TypeField: public BitField<Type, 0, 2> {};
class TypeField: public BitField<Type, 3, 2> {}; class DataField: public BitField<uint32_t, 2, 32 - 3> {};
class DataField: public BitField<uint32_t, 5, 32 - 6> {};
inline void CopyTo(Result* destination) const; inline void CopyTo(Result* destination) const;
......
...@@ -73,7 +73,6 @@ FrameElement VirtualFrame::CopyElementAt(int index) { ...@@ -73,7 +73,6 @@ FrameElement VirtualFrame::CopyElementAt(int index) {
case FrameElement::MEMORY: // Fall through. case FrameElement::MEMORY: // Fall through.
case FrameElement::REGISTER: case FrameElement::REGISTER:
// All copies are backed by memory or register locations. // All copies are backed by memory or register locations.
result.set_static_type(target.static_type());
result.set_type(FrameElement::COPY); result.set_type(FrameElement::COPY);
result.clear_copied(); result.clear_copied();
result.clear_sync(); result.clear_sync();
...@@ -153,7 +152,6 @@ void VirtualFrame::SpillElementAt(int index) { ...@@ -153,7 +152,6 @@ void VirtualFrame::SpillElementAt(int index) {
if (elements_[index].is_register()) { if (elements_[index].is_register()) {
Unuse(elements_[index].reg()); Unuse(elements_[index].reg());
} }
new_element.set_static_type(elements_[index].static_type());
elements_[index] = new_element; elements_[index] = new_element;
} }
...@@ -211,9 +209,6 @@ void VirtualFrame::PrepareMergeTo(VirtualFrame* expected) { ...@@ -211,9 +209,6 @@ void VirtualFrame::PrepareMergeTo(VirtualFrame* expected) {
ASSERT(source.is_valid()); ASSERT(source.is_valid());
elements_[i].clear_sync(); 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) { ...@@ -246,11 +241,8 @@ void VirtualFrame::PrepareForCall(int spilled_args, int dropped_args) {
void VirtualFrame::PrepareForReturn() { void VirtualFrame::PrepareForReturn() {
// Spill all locals. This is necessary to make sure all locals have // Spill all locals. This is necessary to make sure all locals have
// the right value when breaking at the return site in the debugger. // 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++) { for (int i = 0; i < expression_base_index(); i++) {
SpillElementAt(i); SpillElementAt(i);
elements_[i].set_static_type(StaticType::unknown());
} }
} }
...@@ -283,7 +275,6 @@ void VirtualFrame::SetElementAt(int index, Result* value) { ...@@ -283,7 +275,6 @@ void VirtualFrame::SetElementAt(int index, Result* value) {
// register element, or the new element at frame_index, must be made // register element, or the new element at frame_index, must be made
// a copy. // a copy.
int i = register_location(value->reg()); int i = register_location(value->reg());
ASSERT(value->static_type() == elements_[i].static_type());
if (i < frame_index) { if (i < frame_index) {
// The register FrameElement is lower in the frame than the new copy. // The register FrameElement is lower in the frame than the new copy.
...@@ -310,8 +301,7 @@ void VirtualFrame::SetElementAt(int index, Result* value) { ...@@ -310,8 +301,7 @@ void VirtualFrame::SetElementAt(int index, Result* value) {
Use(value->reg(), frame_index); Use(value->reg(), frame_index);
elements_[frame_index] = elements_[frame_index] =
FrameElement::RegisterElement(value->reg(), FrameElement::RegisterElement(value->reg(),
FrameElement::NOT_SYNCED, FrameElement::NOT_SYNCED);
value->static_type());
} }
} else { } else {
ASSERT(value->is_constant()); ASSERT(value->is_constant());
...@@ -328,18 +318,16 @@ void VirtualFrame::PushFrameSlotAt(int index) { ...@@ -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)) { if (is_used(reg)) {
int index = register_location(reg); int index = register_location(reg);
FrameElement element = CopyElementAt(index); FrameElement element = CopyElementAt(index);
ASSERT(static_type.merge(element.static_type()) == element.static_type());
elements_.Add(element); elements_.Add(element);
} else { } else {
Use(reg, element_count()); Use(reg, element_count());
FrameElement element = FrameElement element =
FrameElement::RegisterElement(reg, FrameElement::RegisterElement(reg,
FrameElement::NOT_SYNCED, FrameElement::NOT_SYNCED);
static_type);
elements_.Add(element); elements_.Add(element);
} }
} }
......
...@@ -2368,15 +2368,15 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op, ...@@ -2368,15 +2368,15 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
Result left = frame_->Pop(); Result left = frame_->Pop();
if (op == Token::ADD) { if (op == Token::ADD) {
bool left_is_string = left.static_type().is_jsstring(); bool left_is_string = left.is_constant() && left.handle()->IsString();
bool right_is_string = right.static_type().is_jsstring(); bool right_is_string = right.is_constant() && right.handle()->IsString();
if (left_is_string || right_is_string) { if (left_is_string || right_is_string) {
frame_->Push(&left); frame_->Push(&left);
frame_->Push(&right); frame_->Push(&right);
Result answer; Result answer;
if (left_is_string) { if (left_is_string) {
if (right_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. // -- do a compile time cons, if allocation during codegen is allowed.
answer = frame_->CallRuntime(Runtime::kStringAdd, 2); answer = frame_->CallRuntime(Runtime::kStringAdd, 2);
} else { } else {
...@@ -2387,7 +2387,6 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op, ...@@ -2387,7 +2387,6 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
answer = answer =
frame_->InvokeBuiltin(Builtins::STRING_ADD_RIGHT, CALL_FUNCTION, 2); frame_->InvokeBuiltin(Builtins::STRING_ADD_RIGHT, CALL_FUNCTION, 2);
} }
answer.set_static_type(StaticType::jsstring());
frame_->Push(&answer); frame_->Push(&answer);
return; return;
} }
......
...@@ -432,8 +432,7 @@ void VirtualFrame::MakeMergable() { ...@@ -432,8 +432,7 @@ void VirtualFrame::MakeMergable() {
} }
} }
} }
// No need to set the copied flag---there are no copies. // No need to set the copied flag --- there are no copies.
elements_[i].set_static_type(StaticType::unknown());
} else { } else {
// Clear the copy flag of non-constant, non-copy elements. // Clear the copy flag of non-constant, non-copy elements.
// They cannot be copied because copies are not allowed. // They cannot be copied because copies are not allowed.
...@@ -651,7 +650,6 @@ Result VirtualFrame::Pop() { ...@@ -651,7 +650,6 @@ Result VirtualFrame::Pop() {
if (element.is_memory()) { if (element.is_memory()) {
Result temp = cgen()->allocator()->Allocate(); Result temp = cgen()->allocator()->Allocate();
ASSERT(temp.is_valid()); ASSERT(temp.is_valid());
temp.set_static_type(element.static_type());
__ pop(temp.reg()); __ pop(temp.reg());
return temp; return temp;
} }
...@@ -683,12 +681,11 @@ Result VirtualFrame::Pop() { ...@@ -683,12 +681,11 @@ Result VirtualFrame::Pop() {
FrameElement::RegisterElement(temp.reg(), FrameElement::SYNCED); FrameElement::RegisterElement(temp.reg(), FrameElement::SYNCED);
// Preserve the copy flag on the element. // Preserve the copy flag on the element.
if (element.is_copied()) new_element.set_copied(); if (element.is_copied()) new_element.set_copied();
new_element.set_static_type(element.static_type());
elements_[index] = new_element; elements_[index] = new_element;
__ movq(temp.reg(), Operand(rbp, fp_relative(index))); __ movq(temp.reg(), Operand(rbp, fp_relative(index)));
return Result(temp.reg(), element.static_type()); return Result(temp.reg());
} else if (element.is_register()) { } else if (element.is_register()) {
return Result(element.reg(), element.static_type()); return Result(element.reg());
} else { } else {
ASSERT(element.is_constant()); ASSERT(element.is_constant());
return Result(element.handle()); return Result(element.handle());
......
...@@ -378,7 +378,7 @@ class VirtualFrame : public ZoneObject { ...@@ -378,7 +378,7 @@ class VirtualFrame : public ZoneObject {
void EmitPush(Immediate immediate); void EmitPush(Immediate immediate);
// Push an element on the virtual frame. // 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(Handle<Object> value);
void Push(Smi* value) { Push(Handle<Object>(value)); } void Push(Smi* value) { Push(Handle<Object>(value)); }
...@@ -386,7 +386,7 @@ class VirtualFrame : public ZoneObject { ...@@ -386,7 +386,7 @@ class VirtualFrame : public ZoneObject {
// frame). // frame).
void Push(Result* result) { void Push(Result* result) {
if (result->is_register()) { if (result->is_register()) {
Push(result->reg(), result->static_type()); Push(result->reg());
} else { } else {
ASSERT(result->is_constant()); ASSERT(result->is_constant());
Push(result->handle()); 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