Commit bf3d84e3 authored by rossberg@chromium.org's avatar rossberg@chromium.org

Move more logic from AST to oracle, pt 3

Also eliminates remaining dependencies of type-info on AST.

R=jkummerow@chromium.org
BUG=

Review URL: https://codereview.chromium.org/95033003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18194 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 620c985a
......@@ -580,35 +580,6 @@ void Expression::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
}
void Assignment::RecordTypeFeedback(TypeFeedbackOracle* oracle,
Zone* zone) {
Property* prop = target()->AsProperty();
ASSERT(prop != NULL);
TypeFeedbackId id = AssignmentFeedbackId();
is_uninitialized_ = oracle->StoreIsUninitialized(id);
if (is_uninitialized_) return;
is_pre_monomorphic_ = oracle->StoreIsPreMonomorphic(id);
is_monomorphic_ = oracle->StoreIsMonomorphicNormal(id);
ASSERT(!is_pre_monomorphic_ || !is_monomorphic_);
receiver_types_.Clear();
if (prop->key()->IsPropertyName()) {
Literal* lit_key = prop->key()->AsLiteral();
ASSERT(lit_key != NULL && lit_key->value()->IsString());
Handle<String> name = Handle<String>::cast(lit_key->value());
oracle->StoreReceiverTypes(this, name, &receiver_types_);
} else if (is_monomorphic_) {
// Record receiver type for monomorphic keyed stores.
receiver_types_.Add(oracle->StoreMonomorphicReceiverType(id), zone);
store_mode_ = oracle->GetStoreMode(id);
} else if (oracle->StoreIsKeyedPolymorphic(id)) {
receiver_types_.Reserve(kMaxKeyedPolymorphism, zone);
oracle->CollectKeyedReceiverTypes(id, &receiver_types_);
store_mode_ = oracle->GetStoreMode(id);
}
}
bool Call::ComputeTarget(Handle<Map> type, Handle<String> name) {
// If there is an interceptor, we can't compute the target for a direct call.
if (type->has_named_interceptor()) return false;
......@@ -711,20 +682,21 @@ Handle<JSObject> Call::GetPrototypeForPrimitiveCheck(
void Call::RecordTypeFeedback(TypeFeedbackOracle* oracle,
CallKind call_kind) {
is_monomorphic_ = oracle->CallIsMonomorphic(this);
is_monomorphic_ = oracle->CallIsMonomorphic(CallFeedbackId());
Property* property = expression()->AsProperty();
if (property == NULL) {
// Function call. Specialize for monomorphic calls.
if (is_monomorphic_) target_ = oracle->GetCallTarget(this);
if (is_monomorphic_) target_ = oracle->GetCallTarget(CallFeedbackId());
} else if (property->key()->IsPropertyName()) {
// Method call. Specialize for the receiver types seen at runtime.
Literal* key = property->key()->AsLiteral();
ASSERT(key != NULL && key->value()->IsString());
Handle<String> name = Handle<String>::cast(key->value());
check_type_ = oracle->GetCallCheckType(this);
check_type_ = oracle->GetCallCheckType(CallFeedbackId());
receiver_types_.Clear();
if (check_type_ == RECEIVER_MAP_CHECK) {
oracle->CallReceiverTypes(this, name, call_kind, &receiver_types_);
oracle->CallReceiverTypes(CallFeedbackId(),
name, arguments()->length(), call_kind, &receiver_types_);
is_monomorphic_ = is_monomorphic_ && receiver_types_.length() > 0;
} else {
holder_ = GetPrototypeForPrimitiveCheck(check_type_, oracle->isolate());
......@@ -745,17 +717,19 @@ void Call::RecordTypeFeedback(TypeFeedbackOracle* oracle,
}
} else {
if (is_monomorphic_) {
keyed_array_call_is_holey_ = oracle->KeyedArrayCallIsHoley(this);
keyed_array_call_is_holey_ =
oracle->KeyedArrayCallIsHoley(CallFeedbackId());
}
}
}
void CallNew::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
allocation_info_cell_ = oracle->GetCallNewAllocationInfoCell(this);
is_monomorphic_ = oracle->CallNewIsMonomorphic(this);
allocation_info_cell_ =
oracle->GetCallNewAllocationInfoCell(CallNewFeedbackId());
is_monomorphic_ = oracle->CallNewIsMonomorphic(CallNewFeedbackId());
if (is_monomorphic_) {
target_ = oracle->GetCallNewTarget(this);
target_ = oracle->GetCallNewTarget(CallNewFeedbackId());
Object* value = allocation_info_cell_->value();
ASSERT(!value->IsTheHole());
if (value->IsAllocationSite()) {
......@@ -767,9 +741,9 @@ void CallNew::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
void ObjectLiteral::Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
receiver_type_ = oracle->ObjectLiteralStoreIsMonomorphic(this)
? oracle->GetObjectLiteralStoreMap(this)
: Handle<Map>::null();
TypeFeedbackId id = key()->LiteralFeedbackId();
receiver_type_ = oracle->ObjectLiteralStoreIsMonomorphic(id)
? oracle->GetObjectLiteralStoreMap(id) : Handle<Map>::null();
}
......
......@@ -2142,7 +2142,6 @@ class Assignment V8_FINAL : public Expression {
// Type feedback information.
TypeFeedbackId AssignmentFeedbackId() { return reuse(id()); }
void RecordTypeFeedback(TypeFeedbackOracle* oracle, Zone* zone);
virtual bool IsMonomorphic() V8_OVERRIDE { return is_monomorphic_; }
bool IsUninitialized() { return is_uninitialized_; }
bool IsPreMonomorphic() { return is_pre_monomorphic_; }
......@@ -2155,6 +2154,10 @@ class Assignment V8_FINAL : public Expression {
virtual KeyedAccessStoreMode GetStoreMode() V8_OVERRIDE {
return store_mode_;
}
void set_is_uninitialized(bool b) { is_uninitialized_ = b; }
void set_is_monomorphic(bool b) { is_monomorphic_ = b; }
void set_is_pre_monomorphic(bool b) { is_pre_monomorphic_ = b; }
void set_store_mode(KeyedAccessStoreMode mode) { store_mode_ = mode; }
protected:
Assignment(Isolate* isolate,
......
......@@ -197,30 +197,29 @@ bool TypeFeedbackOracle::StoreIsKeyedPolymorphic(TypeFeedbackId ast_id) {
}
bool TypeFeedbackOracle::CallIsMonomorphic(Call* expr) {
Handle<Object> value = GetInfo(expr->CallFeedbackId());
bool TypeFeedbackOracle::CallIsMonomorphic(TypeFeedbackId id) {
Handle<Object> value = GetInfo(id);
return value->IsMap() || value->IsAllocationSite() || value->IsJSFunction() ||
value->IsSmi() ||
(value->IsCode() && Handle<Code>::cast(value)->ic_state() == MONOMORPHIC);
}
bool TypeFeedbackOracle::KeyedArrayCallIsHoley(Call* expr) {
Handle<Object> value = GetInfo(expr->CallFeedbackId());
bool TypeFeedbackOracle::KeyedArrayCallIsHoley(TypeFeedbackId id) {
Handle<Object> value = GetInfo(id);
Handle<Code> code = Handle<Code>::cast(value);
return KeyedArrayCallStub::IsHoley(code);
}
bool TypeFeedbackOracle::CallNewIsMonomorphic(CallNew* expr) {
Handle<Object> info = GetInfo(expr->CallNewFeedbackId());
bool TypeFeedbackOracle::CallNewIsMonomorphic(TypeFeedbackId id) {
Handle<Object> info = GetInfo(id);
return info->IsAllocationSite() || info->IsJSFunction();
}
bool TypeFeedbackOracle::ObjectLiteralStoreIsMonomorphic(
ObjectLiteral::Property* prop) {
Handle<Object> map_or_code = GetInfo(prop->key()->LiteralFeedbackId());
bool TypeFeedbackOracle::ObjectLiteralStoreIsMonomorphic(TypeFeedbackId id) {
Handle<Object> map_or_code = GetInfo(id);
return map_or_code->IsMap();
}
......@@ -285,22 +284,21 @@ void TypeFeedbackOracle::LoadReceiverTypes(TypeFeedbackId id,
}
void TypeFeedbackOracle::StoreReceiverTypes(Assignment* expr,
void TypeFeedbackOracle::StoreReceiverTypes(TypeFeedbackId id,
Handle<String> name,
SmallMapList* types) {
Code::Flags flags = Code::ComputeFlags(
Code::HANDLER, MONOMORPHIC, kNoExtraICState,
Code::NORMAL, Code::STORE_IC);
CollectReceiverTypes(expr->AssignmentFeedbackId(), name, flags, types);
CollectReceiverTypes(id, name, flags, types);
}
void TypeFeedbackOracle::CallReceiverTypes(Call* expr,
void TypeFeedbackOracle::CallReceiverTypes(TypeFeedbackId id,
Handle<String> name,
int arity,
CallKind call_kind,
SmallMapList* types) {
int arity = expr->arguments()->length();
// Note: Currently we do not take string extra ic data into account
// here.
ContextualMode contextual_mode = call_kind == CALL_AS_FUNCTION
......@@ -311,12 +309,12 @@ void TypeFeedbackOracle::CallReceiverTypes(Call* expr,
Code::Flags flags = Code::ComputeMonomorphicFlags(
Code::CALL_IC, extra_ic_state, OWN_MAP, Code::NORMAL, arity);
CollectReceiverTypes(expr->CallFeedbackId(), name, flags, types);
CollectReceiverTypes(id, name, flags, types);
}
CheckType TypeFeedbackOracle::GetCallCheckType(Call* expr) {
Handle<Object> value = GetInfo(expr->CallFeedbackId());
CheckType TypeFeedbackOracle::GetCallCheckType(TypeFeedbackId id) {
Handle<Object> value = GetInfo(id);
if (!value->IsSmi()) return RECEIVER_MAP_CHECK;
CheckType check = static_cast<CheckType>(Smi::cast(*value)->value());
ASSERT(check != RECEIVER_MAP_CHECK);
......@@ -324,8 +322,8 @@ CheckType TypeFeedbackOracle::GetCallCheckType(Call* expr) {
}
Handle<JSFunction> TypeFeedbackOracle::GetCallTarget(Call* expr) {
Handle<Object> info = GetInfo(expr->CallFeedbackId());
Handle<JSFunction> TypeFeedbackOracle::GetCallTarget(TypeFeedbackId id) {
Handle<Object> info = GetInfo(id);
if (info->IsAllocationSite()) {
return Handle<JSFunction>(isolate_->global_context()->array_function());
} else {
......@@ -334,8 +332,8 @@ Handle<JSFunction> TypeFeedbackOracle::GetCallTarget(Call* expr) {
}
Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(CallNew* expr) {
Handle<Object> info = GetInfo(expr->CallNewFeedbackId());
Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(TypeFeedbackId id) {
Handle<Object> info = GetInfo(id);
if (info->IsAllocationSite()) {
return Handle<JSFunction>(isolate_->global_context()->array_function());
} else {
......@@ -344,15 +342,15 @@ Handle<JSFunction> TypeFeedbackOracle::GetCallNewTarget(CallNew* expr) {
}
Handle<Cell> TypeFeedbackOracle::GetCallNewAllocationInfoCell(CallNew* expr) {
return GetInfoCell(expr->CallNewFeedbackId());
Handle<Cell> TypeFeedbackOracle::GetCallNewAllocationInfoCell(
TypeFeedbackId id) {
return GetInfoCell(id);
}
Handle<Map> TypeFeedbackOracle::GetObjectLiteralStoreMap(
ObjectLiteral::Property* prop) {
ASSERT(ObjectLiteralStoreIsMonomorphic(prop));
return Handle<Map>::cast(GetInfo(prop->key()->LiteralFeedbackId()));
Handle<Map> TypeFeedbackOracle::GetObjectLiteralStoreMap(TypeFeedbackId id) {
ASSERT(ObjectLiteralStoreIsMonomorphic(id));
return Handle<Map>::cast(GetInfo(id));
}
......@@ -482,6 +480,28 @@ void TypeFeedbackOracle::KeyedPropertyReceiverTypes(
}
void TypeFeedbackOracle::AssignmentReceiverTypes(
TypeFeedbackId id, Handle<String> name, SmallMapList* receiver_types) {
receiver_types->Clear();
StoreReceiverTypes(id, name, receiver_types);
}
void TypeFeedbackOracle::KeyedAssignmentReceiverTypes(
TypeFeedbackId id, SmallMapList* receiver_types,
KeyedAccessStoreMode* store_mode) {
receiver_types->Clear();
if (StoreIsMonomorphicNormal(id)) {
// Record receiver type for monomorphic keyed stores.
receiver_types->Add(StoreMonomorphicReceiverType(id), zone());
} else if (StoreIsKeyedPolymorphic(id)) {
receiver_types->Reserve(kMaxKeyedPolymorphism, zone());
CollectKeyedReceiverTypes(id, receiver_types);
}
*store_mode = GetStoreMode(id);
}
void TypeFeedbackOracle::CountReceiverTypes(
TypeFeedbackId id, SmallMapList* receiver_types) {
receiver_types->Clear();
......
......@@ -218,20 +218,9 @@ enum StringStubFeedback {
// Forward declarations.
// TODO(rossberg): these should all go away eventually.
class Assignment;
class Call;
class CallNew;
class CaseClause;
class CompilationInfo;
class CountOperation;
class Expression;
class ForInStatement;
class ICStub;
class Property;
class SmallMapList;
class ObjectLiteral;
class ObjectLiteralProperty;
class TypeFeedbackOracle: public ZoneObject {
......@@ -245,14 +234,14 @@ class TypeFeedbackOracle: public ZoneObject {
bool LoadIsUninitialized(TypeFeedbackId id);
bool LoadIsPreMonomorphic(TypeFeedbackId id);
bool LoadIsPolymorphic(TypeFeedbackId id);
bool StoreIsUninitialized(TypeFeedbackId ast_id);
bool StoreIsMonomorphicNormal(TypeFeedbackId ast_id);
bool StoreIsPreMonomorphic(TypeFeedbackId ast_id);
bool StoreIsKeyedPolymorphic(TypeFeedbackId ast_id);
bool CallIsMonomorphic(Call* expr);
bool KeyedArrayCallIsHoley(Call* expr);
bool CallNewIsMonomorphic(CallNew* expr);
bool ObjectLiteralStoreIsMonomorphic(ObjectLiteralProperty* prop);
bool StoreIsUninitialized(TypeFeedbackId id);
bool StoreIsMonomorphicNormal(TypeFeedbackId id);
bool StoreIsPreMonomorphic(TypeFeedbackId id);
bool StoreIsKeyedPolymorphic(TypeFeedbackId id);
bool CallIsMonomorphic(TypeFeedbackId aid);
bool KeyedArrayCallIsHoley(TypeFeedbackId id);
bool CallNewIsMonomorphic(TypeFeedbackId id);
bool ObjectLiteralStoreIsMonomorphic(TypeFeedbackId id);
// TODO(1571) We can't use ForInStatement::ForInType as the return value due
// to various cycles in our headers.
......@@ -263,21 +252,22 @@ class TypeFeedbackOracle: public ZoneObject {
Handle<Map> LoadMonomorphicReceiverType(TypeFeedbackId id);
Handle<Map> StoreMonomorphicReceiverType(TypeFeedbackId id);
KeyedAccessStoreMode GetStoreMode(TypeFeedbackId ast_id);
KeyedAccessStoreMode GetStoreMode(TypeFeedbackId id);
void LoadReceiverTypes(TypeFeedbackId id,
Handle<String> name,
SmallMapList* types);
void StoreReceiverTypes(Assignment* expr,
void StoreReceiverTypes(TypeFeedbackId id,
Handle<String> name,
SmallMapList* types);
void CallReceiverTypes(Call* expr,
void CallReceiverTypes(TypeFeedbackId id,
Handle<String> name,
int arity,
CallKind call_kind,
SmallMapList* types);
void CollectKeyedReceiverTypes(TypeFeedbackId ast_id,
void CollectKeyedReceiverTypes(TypeFeedbackId id,
SmallMapList* types);
void CollectPolymorphicStoreReceiverTypes(TypeFeedbackId ast_id,
void CollectPolymorphicStoreReceiverTypes(TypeFeedbackId id,
SmallMapList* types);
void PropertyReceiverTypes(TypeFeedbackId id,
......@@ -287,6 +277,12 @@ class TypeFeedbackOracle: public ZoneObject {
void KeyedPropertyReceiverTypes(TypeFeedbackId id,
SmallMapList* receiver_types,
bool* is_string);
void AssignmentReceiverTypes(TypeFeedbackId id,
Handle<String> name,
SmallMapList* receiver_types);
void KeyedAssignmentReceiverTypes(TypeFeedbackId id,
SmallMapList* receiver_types,
KeyedAccessStoreMode* store_mode);
void CountReceiverTypes(TypeFeedbackId id,
SmallMapList* receiver_types);
......@@ -296,12 +292,12 @@ class TypeFeedbackOracle: public ZoneObject {
void CollectPolymorphicMaps(Handle<Code> code, SmallMapList* types);
CheckType GetCallCheckType(Call* expr);
Handle<JSFunction> GetCallTarget(Call* expr);
Handle<JSFunction> GetCallNewTarget(CallNew* expr);
Handle<Cell> GetCallNewAllocationInfoCell(CallNew* expr);
CheckType GetCallCheckType(TypeFeedbackId id);
Handle<JSFunction> GetCallTarget(TypeFeedbackId id);
Handle<JSFunction> GetCallNewTarget(TypeFeedbackId id);
Handle<Cell> GetCallNewAllocationInfoCell(TypeFeedbackId id);
Handle<Map> GetObjectLiteralStoreMap(ObjectLiteralProperty* prop);
Handle<Map> GetObjectLiteralStoreMap(TypeFeedbackId id);
bool LoadIsBuiltin(TypeFeedbackId id, Builtins::Name builtin_id);
bool LoadIsStub(TypeFeedbackId id, ICStub* stub);
......@@ -332,12 +328,12 @@ class TypeFeedbackOracle: public ZoneObject {
Isolate* isolate() const { return isolate_; }
private:
void CollectReceiverTypes(TypeFeedbackId ast_id,
void CollectReceiverTypes(TypeFeedbackId id,
Handle<String> name,
Code::Flags flags,
SmallMapList* types);
void SetInfo(TypeFeedbackId ast_id, Object* target);
void SetInfo(TypeFeedbackId id, Object* target);
void BuildDictionary(Handle<Code> code);
void GetRelocInfos(Handle<Code> code, ZoneList<RelocInfo>* infos);
......@@ -350,10 +346,10 @@ class TypeFeedbackOracle: public ZoneObject {
// Returns an element from the backing store. Returns undefined if
// there is no information.
Handle<Object> GetInfo(TypeFeedbackId ast_id);
Handle<Object> GetInfo(TypeFeedbackId id);
// Return the cell that contains type feedback.
Handle<Cell> GetInfoCell(TypeFeedbackId ast_id);
Handle<Cell> GetInfoCell(TypeFeedbackId id);
private:
Handle<Context> native_context_;
......
......@@ -387,31 +387,35 @@ void AstTyper::VisitArrayLiteral(ArrayLiteral* expr) {
void AstTyper::VisitAssignment(Assignment* expr) {
// TODO(rossberg): Can we clean this up?
if (expr->is_compound()) {
// Collect type feedback.
Expression* target = expr->target();
Property* prop = target->AsProperty();
if (prop != NULL) {
RECURSE(Visit(expr->target()));
expr->RecordTypeFeedback(oracle(), zone());
}
RECURSE(Visit(expr->binary_operation()));
NarrowType(expr, expr->binary_operation()->bounds());
} else {
// Collect type feedback.
if (expr->target()->IsProperty()) {
expr->RecordTypeFeedback(oracle(), zone());
// Collect type feedback.
Property* prop = expr->target()->AsProperty();
if (prop != NULL) {
TypeFeedbackId id = expr->AssignmentFeedbackId();
expr->set_is_uninitialized(oracle()->StoreIsUninitialized(id));
if (!expr->IsUninitialized()) {
expr->set_is_pre_monomorphic(oracle()->StoreIsPreMonomorphic(id));
expr->set_is_monomorphic(oracle()->StoreIsMonomorphicNormal(id));
ASSERT(!expr->IsPreMonomorphic() || !expr->IsMonomorphic());
if (prop->key()->IsPropertyName()) {
Literal* lit_key = prop->key()->AsLiteral();
ASSERT(lit_key != NULL && lit_key->value()->IsString());
Handle<String> name = Handle<String>::cast(lit_key->value());
oracle()->AssignmentReceiverTypes(id, name, expr->GetReceiverTypes());
} else {
KeyedAccessStoreMode store_mode;
oracle()->KeyedAssignmentReceiverTypes(
id, expr->GetReceiverTypes(), &store_mode);
expr->set_store_mode(store_mode);
}
}
RECURSE(Visit(expr->target()));
RECURSE(Visit(expr->value()));
NarrowType(expr, expr->value()->bounds());
}
Expression* rhs =
expr->is_compound() ? expr->binary_operation() : expr->value();
RECURSE(Visit(expr->target()));
RECURSE(Visit(rhs));
NarrowType(expr, rhs->bounds());
VariableProxy* proxy = expr->target()->AsVariableProxy();
if (proxy != NULL && proxy->var()->IsStackAllocated()) {
store_.Seq(variable_index(proxy->var()), Effect(expr->bounds()));
......
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