}
-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;
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());
}
} 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()) {
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();
}
// 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_; }
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,
}
-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();
}
}
-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
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);
}
-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 {
}
-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 {
}
-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));
}
}
+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();
// 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 {
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.
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,
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);
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);
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);
// 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_;
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()));