Commit ac9b035a authored by vitalyr@chromium.org's avatar vitalyr@chromium.org

Expose receiver check type in call type feedback.

This a preparatory step to support fast function calls on primitive
values. Not really used yet in hydrogen.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6300 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 4ea3e060
......@@ -645,10 +645,19 @@ void Call::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
}
}
#endif
if (receiver_types_ != NULL && receiver_types_->length() > 0) {
Handle<Map> type = receiver_types_->at(0);
is_monomorphic_ = oracle->CallIsMonomorphic(this);
if (is_monomorphic_) is_monomorphic_ = ComputeTarget(type, name);
is_monomorphic_ = oracle->CallIsMonomorphic(this);
check_type_ = oracle->GetCallCheckType(this);
if (is_monomorphic_) {
Handle<Map> map;
if (receiver_types_ != NULL && receiver_types_->length() > 0) {
ASSERT(check_type_ == RECEIVER_MAP_CHECK);
map = receiver_types_->at(0);
} else {
ASSERT(check_type_ != RECEIVER_MAP_CHECK);
map = Handle<Map>(
oracle->GetPrototypeForPrimitiveCheck(check_type_)->map());
}
is_monomorphic_ = ComputeTarget(map, name);
}
}
......
......@@ -1268,6 +1268,7 @@ class Call: public Expression {
arguments_(arguments),
pos_(pos),
is_monomorphic_(false),
check_type_(RECEIVER_MAP_CHECK),
receiver_types_(NULL),
return_id_(GetNextId()) {
}
......@@ -1283,6 +1284,7 @@ class Call: public Expression {
void RecordTypeFeedback(TypeFeedbackOracle* oracle);
virtual ZoneMapList* GetReceiverTypes() { return receiver_types_; }
virtual bool IsMonomorphic() { return is_monomorphic_; }
CheckType check_type() const { return check_type_; }
Handle<JSFunction> target() { return target_; }
Handle<JSObject> holder() { return holder_; }
Handle<JSGlobalPropertyCell> cell() { return cell_; }
......@@ -1306,6 +1308,7 @@ class Call: public Expression {
int pos_;
bool is_monomorphic_;
CheckType check_type_;
ZoneMapList* receiver_types_;
Handle<JSFunction> target_;
Handle<JSObject> holder_;
......
......@@ -262,7 +262,9 @@ static bool MakeCrankshaftCode(CompilationInfo* info) {
HTracer::Instance()->TraceCompilation(info->function());
}
TypeFeedbackOracle oracle(Handle<Code>(info->shared_info()->code()));
TypeFeedbackOracle oracle(
Handle<Code>(info->shared_info()->code()),
Handle<Context>(info->closure()->context()->global_context()));
HGraphBuilder builder(&oracle);
HPhase phase(HPhase::kTotal);
HGraph* graph = builder.CreateGraph(info);
......
......@@ -2724,6 +2724,9 @@ MaybeObject* Heap::CreateCode(const CodeDesc& desc,
code->set_instruction_size(desc.instr_size);
code->set_relocation_info(ByteArray::cast(reloc_info));
code->set_flags(flags);
if (code->is_call_stub() || code->is_keyed_call_stub()) {
code->set_check_type(RECEIVER_MAP_CHECK);
}
code->set_deoptimization_data(empty_fixed_array());
// Allow self references to created code object by patching the handle to
// point to the newly allocated Code object.
......
......@@ -4009,7 +4009,9 @@ bool HGraphBuilder::TryInline(Call* expr) {
function_return_->MarkAsInlineReturnTarget();
}
call_context_ = ast_context();
TypeFeedbackOracle new_oracle(Handle<Code>(shared->code()));
TypeFeedbackOracle new_oracle(
Handle<Code>(shared->code()),
Handle<Context>(target->context()->global_context()));
oracle_ = &new_oracle;
graph()->info()->SetOsrAstId(AstNode::kNoNumber);
......@@ -4211,7 +4213,8 @@ bool HGraphBuilder::TryCallApply(Call* expr) {
HValue* arg_two_value = environment()->Lookup(arg_two->var());
if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
if (!expr->IsMonomorphic()) return false;
if (!expr->IsMonomorphic() ||
expr->check_type() != RECEIVER_MAP_CHECK) return false;
// Found pattern f.apply(receiver, arguments).
VisitForValue(prop->obj());
......@@ -4280,7 +4283,7 @@ void HGraphBuilder::VisitCall(Call* expr) {
expr->RecordTypeFeedback(oracle());
ZoneMapList* types = expr->GetReceiverTypes();
if (expr->IsMonomorphic()) {
if (expr->IsMonomorphic() && expr->check_type() == RECEIVER_MAP_CHECK) {
AddCheckConstantFunction(expr, receiver, types->first(), true);
if (TryMathFunctionInline(expr)) {
......@@ -4305,6 +4308,7 @@ void HGraphBuilder::VisitCall(Call* expr) {
}
} else if (types != NULL && types->length() > 1) {
ASSERT(expr->check_type() == RECEIVER_MAP_CHECK);
HandlePolymorphicCallNamed(expr, receiver, types, name);
return;
......
......@@ -58,7 +58,9 @@ TypeInfo TypeInfo::TypeFromValue(Handle<Object> value) {
}
TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code) {
TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code,
Handle<Context> global_context) {
global_context_ = global_context;
Initialize(code);
}
......@@ -71,17 +73,18 @@ void TypeFeedbackOracle::Initialize(Handle<Code> code) {
bool TypeFeedbackOracle::LoadIsMonomorphic(Property* expr) {
return IsMonomorphic(expr->position());
return GetElement(map_, expr->position())->IsMap();
}
bool TypeFeedbackOracle:: StoreIsMonomorphic(Assignment* expr) {
return IsMonomorphic(expr->position());
return GetElement(map_, expr->position())->IsMap();
}
bool TypeFeedbackOracle::CallIsMonomorphic(Call* expr) {
return IsMonomorphic(expr->position());
Handle<Object> value = GetElement(map_, expr->position());
return value->IsMap() || value->IsSmi();
}
......@@ -97,12 +100,6 @@ Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType(Assignment* expr) {
}
Handle<Map> TypeFeedbackOracle::CallMonomorphicReceiverType(Call* expr) {
ASSERT(CallIsMonomorphic(expr));
return Handle<Map>::cast(GetElement(map_, expr->position()));
}
ZoneMapList* TypeFeedbackOracle::LoadReceiverTypes(Property* expr,
Handle<String> name) {
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL);
......@@ -126,6 +123,37 @@ ZoneMapList* TypeFeedbackOracle::CallReceiverTypes(Call* expr,
}
CheckType TypeFeedbackOracle::GetCallCheckType(Call* expr) {
Handle<Object> value = GetElement(map_, expr->position());
if (!value->IsSmi()) return RECEIVER_MAP_CHECK;
CheckType check = static_cast<CheckType>(Smi::cast(*value)->value());
ASSERT(check != RECEIVER_MAP_CHECK);
return check;
}
Handle<JSObject> TypeFeedbackOracle::GetPrototypeForPrimitiveCheck(
CheckType check) {
JSFunction* function = NULL;
switch (check) {
case RECEIVER_MAP_CHECK:
UNREACHABLE();
break;
case STRING_CHECK:
function = global_context_->string_function();
break;
case NUMBER_CHECK:
function = global_context_->number_function();
break;
case BOOLEAN_CHECK:
function = global_context_->boolean_function();
break;
}
ASSERT(function != NULL);
return Handle<JSObject>(JSObject::cast(function->instance_prototype()));
}
bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) {
Handle<Object> object = GetElement(map_, expr->position());
return *object == Builtins::builtin(id);
......@@ -220,6 +248,7 @@ TypeInfo TypeFeedbackOracle::BinaryType(BinaryOperation* expr, Side side) {
return unknown;
}
TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) {
Handle<Object> object = GetElement(map_, clause->position());
TypeInfo unknown = TypeInfo::Unknown();
......@@ -247,12 +276,11 @@ TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) {
}
ZoneMapList* TypeFeedbackOracle::CollectReceiverTypes(int position,
Handle<String> name,
Code::Flags flags) {
Handle<Object> object = GetElement(map_, position);
if (object->IsUndefined()) return NULL;
if (object->IsUndefined() || object->IsSmi()) return NULL;
if (*object == Builtins::builtin(Builtins::StoreIC_GlobalProxy)) {
// TODO(fschneider): We could collect the maps and signal that
......@@ -301,11 +329,20 @@ void TypeFeedbackOracle::PopulateMap(Handle<Code> code) {
SetElement(map_, position, target);
}
} else if (state == MONOMORPHIC) {
Handle<Map> map = Handle<Map>(target->FindFirstMap());
if (*map == NULL) {
SetElement(map_, position, target);
if (target->kind() != Code::CALL_IC ||
target->check_type() == RECEIVER_MAP_CHECK) {
Handle<Map> map = Handle<Map>(target->FindFirstMap());
if (*map == NULL) {
SetElement(map_, position, target);
} else {
SetElement(map_, position, map);
}
} else {
SetElement(map_, position, map);
ASSERT(target->kind() == Code::CALL_IC);
CheckType check = target->check_type();
ASSERT(check != RECEIVER_MAP_CHECK);
SetElement(map_, position, Handle<Object>(Smi::FromInt(check)));
ASSERT(Smi::cast(*GetElement(map_, position))->value() == check);
}
} else if (state == MEGAMORPHIC) {
SetElement(map_, position, target);
......@@ -342,8 +379,6 @@ void TypeFeedbackOracle::CollectPositions(Code* code,
} else if (kind == Code::COMPARE_IC) {
if (target->compare_state() == CompareIC::GENERIC) continue;
} else {
if (kind == Code::CALL_IC && state == MONOMORPHIC &&
target->check_type() != RECEIVER_MAP_CHECK) continue;
if (state != MONOMORPHIC && state != MEGAMORPHIC) continue;
}
code_positions->Add(
......
......@@ -236,7 +236,7 @@ class TypeFeedbackOracle BASE_EMBEDDED {
RESULT
};
explicit TypeFeedbackOracle(Handle<Code> code);
TypeFeedbackOracle(Handle<Code> code, Handle<Context> global_context);
bool LoadIsMonomorphic(Property* expr);
bool StoreIsMonomorphic(Assignment* expr);
......@@ -244,12 +244,14 @@ class TypeFeedbackOracle BASE_EMBEDDED {
Handle<Map> LoadMonomorphicReceiverType(Property* expr);
Handle<Map> StoreMonomorphicReceiverType(Assignment* expr);
Handle<Map> CallMonomorphicReceiverType(Call* expr);
ZoneMapList* LoadReceiverTypes(Property* expr, Handle<String> name);
ZoneMapList* StoreReceiverTypes(Assignment* expr, Handle<String> name);
ZoneMapList* CallReceiverTypes(Call* expr, Handle<String> name);
CheckType GetCallCheckType(Call* expr);
Handle<JSObject> GetPrototypeForPrimitiveCheck(CheckType check);
bool LoadIsBuiltin(Property* expr, Builtins::Name id);
// Get type information for arithmetic operations and compares.
......@@ -260,8 +262,6 @@ class TypeFeedbackOracle BASE_EMBEDDED {
private:
void Initialize(Handle<Code> code);
bool IsMonomorphic(int pos) { return GetElement(map_, pos)->IsMap(); }
ZoneMapList* CollectReceiverTypes(int position,
Handle<String> name,
Code::Flags flags);
......@@ -272,6 +272,7 @@ class TypeFeedbackOracle BASE_EMBEDDED {
List<int>* code_positions,
List<int>* source_positions);
Handle<Context> global_context_;
Handle<JSObject> map_;
DISALLOW_COPY_AND_ASSIGN(TypeFeedbackOracle);
......
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