Revision: 6300
Author: [email protected]
Date: Thu Jan 13 06:16:08 2011
Log: 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
http://code.google.com/p/v8/source/detail?r=6300
Modified:
/branches/bleeding_edge/src/ast.cc
/branches/bleeding_edge/src/ast.h
/branches/bleeding_edge/src/compiler.cc
/branches/bleeding_edge/src/heap.cc
/branches/bleeding_edge/src/hydrogen.cc
/branches/bleeding_edge/src/type-info.cc
/branches/bleeding_edge/src/type-info.h
=======================================
--- /branches/bleeding_edge/src/ast.cc Wed Jan 12 01:29:20 2011
+++ /branches/bleeding_edge/src/ast.cc Thu Jan 13 06:16:08 2011
@@ -645,10 +645,19 @@
}
}
#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);
}
}
=======================================
--- /branches/bleeding_edge/src/ast.h Fri Jan 7 02:36:27 2011
+++ /branches/bleeding_edge/src/ast.h Thu Jan 13 06:16:08 2011
@@ -1268,6 +1268,7 @@
arguments_(arguments),
pos_(pos),
is_monomorphic_(false),
+ check_type_(RECEIVER_MAP_CHECK),
receiver_types_(NULL),
return_id_(GetNextId()) {
}
@@ -1283,6 +1284,7 @@
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 @@
int pos_;
bool is_monomorphic_;
+ CheckType check_type_;
ZoneMapList* receiver_types_;
Handle<JSFunction> target_;
Handle<JSObject> holder_;
=======================================
--- /branches/bleeding_edge/src/compiler.cc Thu Dec 9 05:12:23 2010
+++ /branches/bleeding_edge/src/compiler.cc Thu Jan 13 06:16:08 2011
@@ -262,7 +262,9 @@
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);
=======================================
--- /branches/bleeding_edge/src/heap.cc Tue Jan 11 04:38:19 2011
+++ /branches/bleeding_edge/src/heap.cc Thu Jan 13 06:16:08 2011
@@ -2724,6 +2724,9 @@
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.
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc Wed Jan 12 16:34:08 2011
+++ /branches/bleeding_edge/src/hydrogen.cc Thu Jan 13 06:16:08 2011
@@ -4009,7 +4009,9 @@
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 @@
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 @@
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 @@
}
} else if (types != NULL && types->length() > 1) {
+ ASSERT(expr->check_type() == RECEIVER_MAP_CHECK);
HandlePolymorphicCallNamed(expr, receiver, types, name);
return;
=======================================
--- /branches/bleeding_edge/src/type-info.cc Fri Jan 7 02:36:27 2011
+++ /branches/bleeding_edge/src/type-info.cc Thu Jan 13 06:16:08 2011
@@ -58,7 +58,9 @@
}
-TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code) {
+TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code,
+ Handle<Context> global_context) {
+ global_context_ = global_context;
Initialize(code);
}
@@ -71,17 +73,18 @@
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();
}
@@ -95,12 +98,6 @@
ASSERT(StoreIsMonomorphic(expr));
return Handle<Map>::cast(GetElement(map_, expr->position()));
}
-
-
-Handle<Map> TypeFeedbackOracle::CallMonomorphicReceiverType(Call* expr) {
- ASSERT(CallIsMonomorphic(expr));
- return Handle<Map>::cast(GetElement(map_, expr->position()));
-}
ZoneMapList* TypeFeedbackOracle::LoadReceiverTypes(Property* expr,
@@ -124,6 +121,37 @@
Code::CALL_IC, NORMAL, OWN_MAP, NOT_IN_LOOP, arity);
return CollectReceiverTypes(expr->position(), name, flags);
}
+
+
+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) {
@@ -219,6 +247,7 @@
}
return unknown;
}
+
TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) {
Handle<Object> object = GetElement(map_, clause->position());
@@ -245,14 +274,13 @@
return unknown;
}
}
-
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 @@
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 @@
} 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(
=======================================
--- /branches/bleeding_edge/src/type-info.h Fri Jan 7 02:36:27 2011
+++ /branches/bleeding_edge/src/type-info.h Thu Jan 13 06:16:08 2011
@@ -236,7 +236,7 @@
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 @@
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.
@@ -259,8 +261,6 @@
private:
void Initialize(Handle<Code> code);
-
- bool IsMonomorphic(int pos) { return GetElement(map_, pos)->IsMap(); }
ZoneMapList* CollectReceiverTypes(int position,
Handle<String> name,
@@ -272,6 +272,7 @@
List<int>* code_positions,
List<int>* source_positions);
+ Handle<Context> global_context_;
Handle<JSObject> map_;
DISALLOW_COPY_AND_ASSIGN(TypeFeedbackOracle);
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev