Lattice-based representation inference, powered by left/right specific type...

Lattice-based representation inference, powered by left/right specific type feedback for BinaryOps and comparisons

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12961 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent deae08bd
This diff is collapsed.
...@@ -142,108 +142,6 @@ class UnaryOpStub: public CodeStub { ...@@ -142,108 +142,6 @@ class UnaryOpStub: public CodeStub {
}; };
class BinaryOpStub: public CodeStub {
public:
BinaryOpStub(Token::Value op, OverwriteMode mode)
: op_(op),
mode_(mode),
operands_type_(BinaryOpIC::UNINITIALIZED),
result_type_(BinaryOpIC::UNINITIALIZED) {
use_vfp2_ = CpuFeatures::IsSupported(VFP2);
ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
}
BinaryOpStub(
int key,
BinaryOpIC::TypeInfo operands_type,
BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED)
: op_(OpBits::decode(key)),
mode_(ModeBits::decode(key)),
use_vfp2_(VFP2Bits::decode(key)),
operands_type_(operands_type),
result_type_(result_type) { }
private:
enum SmiCodeGenerateHeapNumberResults {
ALLOW_HEAPNUMBER_RESULTS,
NO_HEAPNUMBER_RESULTS
};
Token::Value op_;
OverwriteMode mode_;
bool use_vfp2_;
// Operand type information determined at runtime.
BinaryOpIC::TypeInfo operands_type_;
BinaryOpIC::TypeInfo result_type_;
virtual void PrintName(StringStream* stream);
// Minor key encoding in 16 bits RRRTTTVOOOOOOOMM.
class ModeBits: public BitField<OverwriteMode, 0, 2> {};
class OpBits: public BitField<Token::Value, 2, 7> {};
class VFP2Bits: public BitField<bool, 9, 1> {};
class OperandTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 10, 3> {};
class ResultTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 13, 3> {};
Major MajorKey() { return BinaryOp; }
int MinorKey() {
return OpBits::encode(op_)
| ModeBits::encode(mode_)
| VFP2Bits::encode(use_vfp2_)
| OperandTypeInfoBits::encode(operands_type_)
| ResultTypeInfoBits::encode(result_type_);
}
void Generate(MacroAssembler* masm);
void GenerateGeneric(MacroAssembler* masm);
void GenerateSmiSmiOperation(MacroAssembler* masm);
void GenerateFPOperation(MacroAssembler* masm,
bool smi_operands,
Label* not_numbers,
Label* gc_required);
void GenerateSmiCode(MacroAssembler* masm,
Label* use_runtime,
Label* gc_required,
SmiCodeGenerateHeapNumberResults heapnumber_results);
void GenerateLoadArguments(MacroAssembler* masm);
void GenerateReturn(MacroAssembler* masm);
void GenerateUninitializedStub(MacroAssembler* masm);
void GenerateSmiStub(MacroAssembler* masm);
void GenerateInt32Stub(MacroAssembler* masm);
void GenerateHeapNumberStub(MacroAssembler* masm);
void GenerateOddballStub(MacroAssembler* masm);
void GenerateStringStub(MacroAssembler* masm);
void GenerateBothStringStub(MacroAssembler* masm);
void GenerateGenericStub(MacroAssembler* masm);
void GenerateAddStrings(MacroAssembler* masm);
void GenerateCallRuntime(MacroAssembler* masm);
void GenerateHeapResultAllocation(MacroAssembler* masm,
Register result,
Register heap_number_map,
Register scratch1,
Register scratch2,
Label* gc_required);
void GenerateRegisterArgsPush(MacroAssembler* masm);
void GenerateTypeTransition(MacroAssembler* masm);
void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm);
virtual int GetCodeKind() { return Code::BINARY_OP_IC; }
virtual InlineCacheState GetICState() {
return BinaryOpIC::ToState(operands_type_);
}
virtual void FinishCode(Handle<Code> code) {
code->set_binary_op_type(operands_type_);
code->set_binary_op_result_type(result_type_);
}
friend class CodeGenerator;
};
class StringHelper : public AllStatic { class StringHelper : public AllStatic {
public: public:
// Generate code for copying characters using a simple loop. This should only // Generate code for copying characters using a simple loop. This should only
...@@ -724,20 +622,6 @@ class FloatingPointHelper : public AllStatic { ...@@ -724,20 +622,6 @@ class FloatingPointHelper : public AllStatic {
Register scratch1, Register scratch1,
Register scratch2); Register scratch2);
// Loads objects from r0 and r1 (right and left in binary operations) into
// floating point registers. Depending on the destination the values ends up
// either d7 and d6 or in r2/r3 and r0/r1 respectively. If the destination is
// floating point registers VFP3 must be supported. If core registers are
// requested when VFP3 is supported d6 and d7 will still be scratched. If
// either r0 or r1 is not a number (not smi and not heap number object) the
// not_number label is jumped to with r0 and r1 intact.
static void LoadOperands(MacroAssembler* masm,
FloatingPointHelper::Destination destination,
Register heap_number_map,
Register scratch1,
Register scratch2,
Label* not_number);
// Convert the smi or heap number in object to an int32 using the rules // Convert the smi or heap number in object to an int32 using the rules
// for ToInt32 as described in ECMAScript 9.5.: the value is truncated // for ToInt32 as described in ECMAScript 9.5.: the value is truncated
// and brought into the range -2^31 .. +2^31 - 1. // and brought into the range -2^31 .. +2^31 - 1.
...@@ -836,7 +720,12 @@ class FloatingPointHelper : public AllStatic { ...@@ -836,7 +720,12 @@ class FloatingPointHelper : public AllStatic {
Register heap_number_result, Register heap_number_result,
Register scratch); Register scratch);
private: // Loads the objects from |object| into floating point registers.
// Depending on |destination| the value ends up either in |dst| or
// in |dst1|/|dst2|. If |destination| is kVFPRegisters, then VFP3
// must be supported. If kCoreRegisters are requested and VFP3 is
// supported, |dst| will be scratched. If |object| is neither smi nor
// heap number, |not_number| is jumped to with |object| still intact.
static void LoadNumber(MacroAssembler* masm, static void LoadNumber(MacroAssembler* masm,
FloatingPointHelper::Destination destination, FloatingPointHelper::Destination destination,
Register object, Register object,
......
...@@ -4073,7 +4073,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4073,7 +4073,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// Call stub. Undo operation first. // Call stub. Undo operation first.
__ sub(r0, r0, Operand(Smi::FromInt(count_value))); __ sub(r0, r0, Operand(Smi::FromInt(count_value)));
} }
__ mov(r1, Operand(Smi::FromInt(count_value))); __ mov(r1, r0);
__ mov(r0, Operand(Smi::FromInt(count_value)));
// Record position before stub call. // Record position before stub call.
SetSourcePosition(expr->position()); SetSourcePosition(expr->position());
...@@ -4298,29 +4299,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { ...@@ -4298,29 +4299,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
default: { default: {
VisitForAccumulatorValue(expr->right()); VisitForAccumulatorValue(expr->right());
Condition cond = eq; Condition cond = CompareIC::ComputeCondition(op);
switch (op) {
case Token::EQ_STRICT:
case Token::EQ:
cond = eq;
break;
case Token::LT:
cond = lt;
break;
case Token::GT:
cond = gt;
break;
case Token::LTE:
cond = le;
break;
case Token::GTE:
cond = ge;
break;
case Token::IN:
case Token::INSTANCEOF:
default:
UNREACHABLE();
}
__ pop(r1); __ pop(r1);
bool inline_smi_code = ShouldInlineSmiCase(op); bool inline_smi_code = ShouldInlineSmiCase(op);
......
...@@ -1699,36 +1699,15 @@ Condition CompareIC::ComputeCondition(Token::Value op) { ...@@ -1699,36 +1699,15 @@ Condition CompareIC::ComputeCondition(Token::Value op) {
} }
void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { bool CompareIC::HasInlinedSmiCode(Address address) {
HandleScope scope; // The address of the instruction following the call.
Handle<Code> rewritten; Address cmp_instruction_address =
State previous_state = GetState(); Assembler::return_address_from_call_start(address);
State state = TargetState(previous_state, false, x, y);
if (state == GENERIC) {
CompareStub stub(GetCondition(), strict(), NO_COMPARE_FLAGS, r1, r0);
rewritten = stub.GetCode();
} else {
ICCompareStub stub(op_, state);
if (state == KNOWN_OBJECTS) {
stub.set_known_map(Handle<Map>(Handle<JSObject>::cast(x)->map()));
}
rewritten = stub.GetCode();
}
set_target(*rewritten);
#ifdef DEBUG
if (FLAG_trace_ic) {
PrintF("[CompareIC (%s->%s)#%s]\n",
GetStateName(previous_state),
GetStateName(state),
Token::Name(op_));
}
#endif
// Activate inlined smi code. // If the instruction following the call is not a cmp rx, #yyy, nothing
if (previous_state == UNINITIALIZED) { // was inlined.
PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK); Instr instr = Assembler::instr_at(cmp_instruction_address);
} return Assembler::IsCmpImmediate(instr);
} }
......
...@@ -1437,7 +1437,7 @@ LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) { ...@@ -1437,7 +1437,7 @@ LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
LInstruction* LChunkBuilder::DoCompareIDAndBranch( LInstruction* LChunkBuilder::DoCompareIDAndBranch(
HCompareIDAndBranch* instr) { HCompareIDAndBranch* instr) {
Representation r = instr->GetInputRepresentation(); Representation r = instr->representation();
if (r.IsInteger32()) { if (r.IsInteger32()) {
ASSERT(instr->left()->representation().IsInteger32()); ASSERT(instr->left()->representation().IsInteger32());
ASSERT(instr->right()->representation().IsInteger32()); ASSERT(instr->right()->representation().IsInteger32());
...@@ -2196,7 +2196,7 @@ LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { ...@@ -2196,7 +2196,7 @@ LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
env->set_ast_id(instr->ast_id()); env->set_ast_id(instr->ast_id());
env->Drop(instr->pop_count()); env->Drop(instr->pop_count());
for (int i = 0; i < instr->values()->length(); ++i) { for (int i = instr->values()->length() - 1; i >= 0; --i) {
HValue* value = instr->values()->at(i); HValue* value = instr->values()->at(i);
if (instr->HasAssignedIndexAt(i)) { if (instr->HasAssignedIndexAt(i)) {
env->Bind(instr->GetAssignedIndexAt(i), value); env->Bind(instr->GetAssignedIndexAt(i), value);
......
...@@ -655,7 +655,7 @@ class LCmpIDAndBranch: public LControlInstruction<2, 0> { ...@@ -655,7 +655,7 @@ class LCmpIDAndBranch: public LControlInstruction<2, 0> {
Token::Value op() const { return hydrogen()->token(); } Token::Value op() const { return hydrogen()->token(); }
bool is_double() const { bool is_double() const {
return hydrogen()->GetInputRepresentation().IsDouble(); return hydrogen()->representation().IsDouble();
} }
virtual void PrintDataTo(StringStream* stream); virtual void PrintDataTo(StringStream* stream);
......
...@@ -230,7 +230,30 @@ bool LCodeGen::GenerateBody() { ...@@ -230,7 +230,30 @@ bool LCodeGen::GenerateBody() {
} }
if (emit_instructions) { if (emit_instructions) {
Comment(";;; @%d: %s.", current_instruction_, instr->Mnemonic()); if (FLAG_code_comments) {
HValue* hydrogen = instr->hydrogen_value();
if (hydrogen != NULL) {
if (hydrogen->IsChange()) {
HValue* changed_value = HChange::cast(hydrogen)->value();
int use_id = 0;
const char* use_mnemo = "dead";
if (hydrogen->UseCount() >= 1) {
HValue* use_value = hydrogen->uses().value();
use_id = use_value->id();
use_mnemo = use_value->Mnemonic();
}
Comment(";;; @%d: %s. <of #%d %s for #%d %s>",
current_instruction_, instr->Mnemonic(),
changed_value->id(), changed_value->Mnemonic(),
use_id, use_mnemo);
} else {
Comment(";;; @%d: %s. <#%d>", current_instruction_,
instr->Mnemonic(), hydrogen->id());
}
} else {
Comment(";;; @%d: %s.", current_instruction_, instr->Mnemonic());
}
}
instr->CompileToNative(this); instr->CompileToNative(this);
} }
} }
......
...@@ -476,6 +476,7 @@ void CountOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle, ...@@ -476,6 +476,7 @@ void CountOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle,
void CaseClause::RecordTypeFeedback(TypeFeedbackOracle* oracle) { void CaseClause::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
TypeInfo info = oracle->SwitchType(this); TypeInfo info = oracle->SwitchType(this);
if (info.IsUninitialized()) info = TypeInfo::Unknown();
if (info.IsSmi()) { if (info.IsSmi()) {
compare_type_ = SMI_ONLY; compare_type_ = SMI_ONLY;
} else if (info.IsSymbol()) { } else if (info.IsSymbol()) {
...@@ -604,18 +605,6 @@ void CallNew::RecordTypeFeedback(TypeFeedbackOracle* oracle) { ...@@ -604,18 +605,6 @@ void CallNew::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
} }
void CompareOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
TypeInfo info = oracle->CompareType(this);
if (info.IsSmi()) {
compare_type_ = SMI_ONLY;
} else if (info.IsNonPrimitive()) {
compare_type_ = OBJECT_ONLY;
} else {
ASSERT(compare_type_ == NONE);
}
}
void ObjectLiteral::Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) { void ObjectLiteral::Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
receiver_type_ = oracle->ObjectLiteralStoreIsMonomorphic(this) receiver_type_ = oracle->ObjectLiteralStoreIsMonomorphic(this)
? oracle->GetObjectLiteralStoreMap(this) ? oracle->GetObjectLiteralStoreMap(this)
......
...@@ -1777,9 +1777,6 @@ class CompareOperation: public Expression { ...@@ -1777,9 +1777,6 @@ class CompareOperation: public Expression {
// Type feedback information. // Type feedback information.
TypeFeedbackId CompareOperationFeedbackId() const { return reuse(id()); } TypeFeedbackId CompareOperationFeedbackId() const { return reuse(id()); }
void RecordTypeFeedback(TypeFeedbackOracle* oracle);
bool IsSmiCompare() { return compare_type_ == SMI_ONLY; }
bool IsObjectCompare() { return compare_type_ == OBJECT_ONLY; }
// Match special cases. // Match special cases.
bool IsLiteralCompareTypeof(Expression** expr, Handle<String>* check); bool IsLiteralCompareTypeof(Expression** expr, Handle<String>* check);
...@@ -1796,8 +1793,7 @@ class CompareOperation: public Expression { ...@@ -1796,8 +1793,7 @@ class CompareOperation: public Expression {
op_(op), op_(op),
left_(left), left_(left),
right_(right), right_(right),
pos_(pos), pos_(pos) {
compare_type_(NONE) {
ASSERT(Token::IsCompareOp(op)); ASSERT(Token::IsCompareOp(op));
} }
...@@ -1806,9 +1802,6 @@ class CompareOperation: public Expression { ...@@ -1806,9 +1802,6 @@ class CompareOperation: public Expression {
Expression* left_; Expression* left_;
Expression* right_; Expression* right_;
int pos_; int pos_;
enum CompareTypeFeedback { NONE, SMI_ONLY, OBJECT_ONLY };
CompareTypeFeedback compare_type_;
}; };
......
...@@ -169,6 +169,122 @@ void CodeStub::PrintName(StringStream* stream) { ...@@ -169,6 +169,122 @@ void CodeStub::PrintName(StringStream* stream) {
} }
void BinaryOpStub::Generate(MacroAssembler* masm) {
// Explicitly allow generation of nested stubs. It is safe here because
// generation code does not use any raw pointers.
AllowStubCallsScope allow_stub_calls(masm, true);
BinaryOpIC::TypeInfo operands_type = Max(left_type_, right_type_);
if (left_type_ == BinaryOpIC::ODDBALL && right_type_ == BinaryOpIC::ODDBALL) {
// The OddballStub handles a number and an oddball, not two oddballs.
operands_type = BinaryOpIC::GENERIC;
}
switch (operands_type) {
case BinaryOpIC::UNINITIALIZED:
GenerateTypeTransition(masm);
break;
case BinaryOpIC::SMI:
GenerateSmiStub(masm);
break;
case BinaryOpIC::INT32:
GenerateInt32Stub(masm);
break;
case BinaryOpIC::HEAP_NUMBER:
GenerateHeapNumberStub(masm);
break;
case BinaryOpIC::ODDBALL:
GenerateOddballStub(masm);
break;
case BinaryOpIC::STRING:
GenerateStringStub(masm);
break;
case BinaryOpIC::GENERIC:
GenerateGeneric(masm);
break;
default:
UNREACHABLE();
}
}
#define __ ACCESS_MASM(masm)
void BinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) {
switch (op_) {
case Token::ADD:
__ InvokeBuiltin(Builtins::ADD, JUMP_FUNCTION);
break;
case Token::SUB:
__ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION);
break;
case Token::MUL:
__ InvokeBuiltin(Builtins::MUL, JUMP_FUNCTION);
break;
case Token::DIV:
__ InvokeBuiltin(Builtins::DIV, JUMP_FUNCTION);
break;
case Token::MOD:
__ InvokeBuiltin(Builtins::MOD, JUMP_FUNCTION);
break;
case Token::BIT_OR:
__ InvokeBuiltin(Builtins::BIT_OR, JUMP_FUNCTION);
break;
case Token::BIT_AND:
__ InvokeBuiltin(Builtins::BIT_AND, JUMP_FUNCTION);
break;
case Token::BIT_XOR:
__ InvokeBuiltin(Builtins::BIT_XOR, JUMP_FUNCTION);
break;
case Token::SAR:
__ InvokeBuiltin(Builtins::SAR, JUMP_FUNCTION);
break;
case Token::SHR:
__ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION);
break;
case Token::SHL:
__ InvokeBuiltin(Builtins::SHL, JUMP_FUNCTION);
break;
default:
UNREACHABLE();
}
}
#undef __
void BinaryOpStub::PrintName(StringStream* stream) {
const char* op_name = Token::Name(op_);
const char* overwrite_name;
switch (mode_) {
case NO_OVERWRITE: overwrite_name = "Alloc"; break;
case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break;
case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break;
default: overwrite_name = "UnknownOverwrite"; break;
}
stream->Add("BinaryOpStub_%s_%s_%s+%s",
op_name,
overwrite_name,
BinaryOpIC::GetName(left_type_),
BinaryOpIC::GetName(right_type_));
}
void BinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
ASSERT(left_type_ == BinaryOpIC::STRING || right_type_ == BinaryOpIC::STRING);
ASSERT(op_ == Token::ADD);
if (left_type_ == BinaryOpIC::STRING && right_type_ == BinaryOpIC::STRING) {
GenerateBothStringStub(masm);
return;
}
// Try to add arguments as strings, otherwise, transition to the generic
// BinaryOpIC type.
GenerateAddStrings(masm);
GenerateTypeTransition(masm);
}
void ICCompareStub::AddToSpecialCache(Handle<Code> new_object) { void ICCompareStub::AddToSpecialCache(Handle<Code> new_object) {
ASSERT(*known_map_ != NULL); ASSERT(*known_map_ != NULL);
Isolate* isolate = new_object->GetIsolate(); Isolate* isolate = new_object->GetIsolate();
...@@ -196,7 +312,12 @@ bool ICCompareStub::FindCodeInSpecialCache(Code** code_out) { ...@@ -196,7 +312,12 @@ bool ICCompareStub::FindCodeInSpecialCache(Code** code_out) {
flags)); flags));
if (probe->IsCode()) { if (probe->IsCode()) {
*code_out = Code::cast(*probe); *code_out = Code::cast(*probe);
ASSERT(op_ == (*code_out)->compare_operation() + Token::EQ); #ifdef DEBUG
Token::Value cached_op;
ICCompareStub::DecodeMinorKey((*code_out)->stub_info(), NULL, NULL, NULL,
&cached_op);
ASSERT(op_ == cached_op);
#endif
return true; return true;
} }
return false; return false;
...@@ -204,7 +325,33 @@ bool ICCompareStub::FindCodeInSpecialCache(Code** code_out) { ...@@ -204,7 +325,33 @@ bool ICCompareStub::FindCodeInSpecialCache(Code** code_out) {
int ICCompareStub::MinorKey() { int ICCompareStub::MinorKey() {
return OpField::encode(op_ - Token::EQ) | StateField::encode(state_); return OpField::encode(op_ - Token::EQ) |
LeftStateField::encode(left_) |
RightStateField::encode(right_) |
HandlerStateField::encode(state_);
}
void ICCompareStub::DecodeMinorKey(int minor_key,
CompareIC::State* left_state,
CompareIC::State* right_state,
CompareIC::State* handler_state,
Token::Value* op) {
if (left_state) {
*left_state =
static_cast<CompareIC::State>(LeftStateField::decode(minor_key));
}
if (right_state) {
*right_state =
static_cast<CompareIC::State>(RightStateField::decode(minor_key));
}
if (handler_state) {
*handler_state =
static_cast<CompareIC::State>(HandlerStateField::decode(minor_key));
}
if (op) {
*op = static_cast<Token::Value>(OpField::decode(minor_key) + Token::EQ);
}
} }
...@@ -213,27 +360,28 @@ void ICCompareStub::Generate(MacroAssembler* masm) { ...@@ -213,27 +360,28 @@ void ICCompareStub::Generate(MacroAssembler* masm) {
case CompareIC::UNINITIALIZED: case CompareIC::UNINITIALIZED:
GenerateMiss(masm); GenerateMiss(masm);
break; break;
case CompareIC::SMIS: case CompareIC::SMI:
GenerateSmis(masm); GenerateSmis(masm);
break; break;
case CompareIC::HEAP_NUMBERS: case CompareIC::HEAP_NUMBER:
GenerateHeapNumbers(masm); GenerateHeapNumbers(masm);
break; break;
case CompareIC::STRINGS: case CompareIC::STRING:
GenerateStrings(masm); GenerateStrings(masm);
break; break;
case CompareIC::SYMBOLS: case CompareIC::SYMBOL:
GenerateSymbols(masm); GenerateSymbols(masm);
break; break;
case CompareIC::OBJECTS: case CompareIC::OBJECT:
GenerateObjects(masm); GenerateObjects(masm);
break; break;
case CompareIC::KNOWN_OBJECTS: case CompareIC::KNOWN_OBJECTS:
ASSERT(*known_map_ != NULL); ASSERT(*known_map_ != NULL);
GenerateKnownObjects(masm); GenerateKnownObjects(masm);
break; break;
default: case CompareIC::GENERIC:
UNREACHABLE(); GenerateGeneric(masm);
break;
} }
} }
......
This diff is collapsed.
...@@ -107,7 +107,7 @@ function MakeDay(year, month, date) { ...@@ -107,7 +107,7 @@ function MakeDay(year, month, date) {
} }
// Now we rely on year and month being SMIs. // Now we rely on year and month being SMIs.
return %DateMakeDay(year, month) + date - 1; return %DateMakeDay(year | 0, month | 0) + date - 1;
} }
......
...@@ -3787,7 +3787,7 @@ MaybeObject* Heap::CreateCode(const CodeDesc& desc, ...@@ -3787,7 +3787,7 @@ MaybeObject* Heap::CreateCode(const CodeDesc& desc,
code->set_check_type(RECEIVER_MAP_CHECK); code->set_check_type(RECEIVER_MAP_CHECK);
} }
code->set_deoptimization_data(empty_fixed_array(), SKIP_WRITE_BARRIER); code->set_deoptimization_data(empty_fixed_array(), SKIP_WRITE_BARRIER);
code->set_type_feedback_info(undefined_value(), SKIP_WRITE_BARRIER); code->InitializeTypeFeedbackInfoNoWriteBarrier(undefined_value());
code->set_handler_table(empty_fixed_array(), SKIP_WRITE_BARRIER); code->set_handler_table(empty_fixed_array(), SKIP_WRITE_BARRIER);
code->set_gc_metadata(Smi::FromInt(0)); code->set_gc_metadata(Smi::FromInt(0));
code->set_ic_age(global_ic_age_); code->set_ic_age(global_ic_age_);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -125,7 +125,10 @@ class HBasicBlock: public ZoneObject { ...@@ -125,7 +125,10 @@ class HBasicBlock: public ZoneObject {
void Goto(HBasicBlock* block, FunctionState* state = NULL); void Goto(HBasicBlock* block, FunctionState* state = NULL);
int PredecessorIndexOf(HBasicBlock* predecessor) const; int PredecessorIndexOf(HBasicBlock* predecessor) const;
void AddSimulate(BailoutId ast_id) { AddInstruction(CreateSimulate(ast_id)); } void AddSimulate(BailoutId ast_id,
RemovableSimulate removable = FIXED_SIMULATE) {
AddInstruction(CreateSimulate(ast_id, removable));
}
void AssignCommonDominator(HBasicBlock* other); void AssignCommonDominator(HBasicBlock* other);
void AssignLoopSuccessorDominators(); void AssignLoopSuccessorDominators();
...@@ -166,7 +169,7 @@ class HBasicBlock: public ZoneObject { ...@@ -166,7 +169,7 @@ class HBasicBlock: public ZoneObject {
void RegisterPredecessor(HBasicBlock* pred); void RegisterPredecessor(HBasicBlock* pred);
void AddDominatedBlock(HBasicBlock* block); void AddDominatedBlock(HBasicBlock* block);
HSimulate* CreateSimulate(BailoutId ast_id); HSimulate* CreateSimulate(BailoutId ast_id, RemovableSimulate removable);
HDeoptimize* CreateDeoptimize(HDeoptimize::UseEnvironment has_uses); HDeoptimize* CreateDeoptimize(HDeoptimize::UseEnvironment has_uses);
int block_id_; int block_id_;
...@@ -255,6 +258,7 @@ class HGraph: public ZoneObject { ...@@ -255,6 +258,7 @@ class HGraph: public ZoneObject {
void InitializeInferredTypes(); void InitializeInferredTypes();
void InsertTypeConversions(); void InsertTypeConversions();
void MergeRemovableSimulates();
void InsertRepresentationChanges(); void InsertRepresentationChanges();
void MarkDeoptimizeOnUndefined(); void MarkDeoptimizeOnUndefined();
void ComputeMinusZeroChecks(); void ComputeMinusZeroChecks();
...@@ -613,6 +617,25 @@ class HEnvironment: public ZoneObject { ...@@ -613,6 +617,25 @@ class HEnvironment: public ZoneObject {
}; };
class HInferRepresentation BASE_EMBEDDED {
public:
explicit HInferRepresentation(HGraph* graph)
: graph_(graph),
worklist_(8, graph->zone()),
in_worklist_(graph->GetMaximumValueID(), graph->zone()) { }
void Analyze();
void AddToWorklist(HValue* current);
private:
Zone* zone() const { return graph_->zone(); }
HGraph* graph_;
ZoneList<HValue*> worklist_;
BitVector in_worklist_;
};
class HGraphBuilder; class HGraphBuilder;
enum ArgumentsAllowedFlag { enum ArgumentsAllowedFlag {
...@@ -880,7 +903,8 @@ class HGraphBuilder: public AstVisitor { ...@@ -880,7 +903,8 @@ class HGraphBuilder: public AstVisitor {
// Adding instructions. // Adding instructions.
HInstruction* AddInstruction(HInstruction* instr); HInstruction* AddInstruction(HInstruction* instr);
void AddSimulate(BailoutId ast_id); void AddSimulate(BailoutId ast_id,
RemovableSimulate removable = FIXED_SIMULATE);
// Bailout environment manipulation. // Bailout environment manipulation.
void Push(HValue* value) { environment()->Push(value); } void Push(HValue* value) { environment()->Push(value); }
...@@ -1025,10 +1049,6 @@ class HGraphBuilder: public AstVisitor { ...@@ -1025,10 +1049,6 @@ class HGraphBuilder: public AstVisitor {
// to push them as outgoing parameters. // to push them as outgoing parameters.
template <class Instruction> HInstruction* PreProcessCall(Instruction* call); template <class Instruction> HInstruction* PreProcessCall(Instruction* call);
void TraceRepresentation(Token::Value op,
TypeInfo info,
HValue* value,
Representation rep);
static Representation ToRepresentation(TypeInfo info); static Representation ToRepresentation(TypeInfo info);
void SetUpScope(Scope* scope); void SetUpScope(Scope* scope);
......
This diff is collapsed.
...@@ -154,96 +154,6 @@ class UnaryOpStub: public CodeStub { ...@@ -154,96 +154,6 @@ class UnaryOpStub: public CodeStub {
}; };
class BinaryOpStub: public CodeStub {
public:
BinaryOpStub(Token::Value op, OverwriteMode mode)
: op_(op),
mode_(mode),
operands_type_(BinaryOpIC::UNINITIALIZED),
result_type_(BinaryOpIC::UNINITIALIZED) {
use_sse3_ = CpuFeatures::IsSupported(SSE3);
ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
}
BinaryOpStub(
int key,
BinaryOpIC::TypeInfo operands_type,
BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED)
: op_(OpBits::decode(key)),
mode_(ModeBits::decode(key)),
use_sse3_(SSE3Bits::decode(key)),
operands_type_(operands_type),
result_type_(result_type) { }
private:
enum SmiCodeGenerateHeapNumberResults {
ALLOW_HEAPNUMBER_RESULTS,
NO_HEAPNUMBER_RESULTS
};
Token::Value op_;
OverwriteMode mode_;
bool use_sse3_;
// Operand type information determined at runtime.
BinaryOpIC::TypeInfo operands_type_;
BinaryOpIC::TypeInfo result_type_;
virtual void PrintName(StringStream* stream);
// Minor key encoding in 16 bits RRRTTTSOOOOOOOMM.
class ModeBits: public BitField<OverwriteMode, 0, 2> {};
class OpBits: public BitField<Token::Value, 2, 7> {};
class SSE3Bits: public BitField<bool, 9, 1> {};
class OperandTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 10, 3> {};
class ResultTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 13, 3> {};
Major MajorKey() { return BinaryOp; }
int MinorKey() {
return OpBits::encode(op_)
| ModeBits::encode(mode_)
| SSE3Bits::encode(use_sse3_)
| OperandTypeInfoBits::encode(operands_type_)
| ResultTypeInfoBits::encode(result_type_);
}
void Generate(MacroAssembler* masm);
void GenerateGeneric(MacroAssembler* masm);
void GenerateSmiCode(MacroAssembler* masm,
Label* slow,
SmiCodeGenerateHeapNumberResults heapnumber_results);
void GenerateLoadArguments(MacroAssembler* masm);
void GenerateReturn(MacroAssembler* masm);
void GenerateUninitializedStub(MacroAssembler* masm);
void GenerateSmiStub(MacroAssembler* masm);
void GenerateInt32Stub(MacroAssembler* masm);
void GenerateHeapNumberStub(MacroAssembler* masm);
void GenerateOddballStub(MacroAssembler* masm);
void GenerateStringStub(MacroAssembler* masm);
void GenerateBothStringStub(MacroAssembler* masm);
void GenerateGenericStub(MacroAssembler* masm);
void GenerateAddStrings(MacroAssembler* masm);
void GenerateHeapResultAllocation(MacroAssembler* masm, Label* alloc_failure);
void GenerateRegisterArgsPush(MacroAssembler* masm);
void GenerateTypeTransition(MacroAssembler* masm);
void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm);
virtual int GetCodeKind() { return Code::BINARY_OP_IC; }
virtual InlineCacheState GetICState() {
return BinaryOpIC::ToState(operands_type_);
}
virtual void FinishCode(Handle<Code> code) {
code->set_binary_op_type(operands_type_);
code->set_binary_op_result_type(result_type_);
}
friend class CodeGenerator;
};
class StringHelper : public AllStatic { class StringHelper : public AllStatic {
public: public:
// Generate code for copying characters using a simple loop. This should only // Generate code for copying characters using a simple loop. This should only
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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