Improve memory usage of receiver type feedback.
Some AST nodes (Property, Call, etc.) store either a list of receiver types or a monomorphic receiver type. This patch merges the two fields using a small pointer list. GetMonomorphicReceiverType() is now a purely convenience function returning the first and only recorded type. This saves about 500K (of about 39M) on average when compiling V8 benchmark as measured by a simple patch adding a zone allocation counter (https://gist.github.com/1149397). R=kmillikin@chromium.org Review URL: http://codereview.chromium.org/7655017 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8993 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
107d1b5e65
commit
633e615b89
43
src/ast.cc
43
src/ast.cc
@ -139,8 +139,7 @@ Assignment::Assignment(Isolate* isolate,
|
||||
assignment_id_(GetNextId(isolate)),
|
||||
block_start_(false),
|
||||
block_end_(false),
|
||||
is_monomorphic_(false),
|
||||
receiver_types_(NULL) {
|
||||
is_monomorphic_(false) {
|
||||
ASSERT(Token::IsAssignmentOp(op));
|
||||
if (is_compound()) {
|
||||
binary_operation_ =
|
||||
@ -652,6 +651,7 @@ bool CountOperation::IsInlineable() const {
|
||||
void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
|
||||
// Record type feedback from the oracle in the AST.
|
||||
is_monomorphic_ = oracle->LoadIsMonomorphicNormal(this);
|
||||
receiver_types_.Clear();
|
||||
if (key()->IsPropertyName()) {
|
||||
if (oracle->LoadIsBuiltin(this, Builtins::kLoadIC_ArrayLength)) {
|
||||
is_array_length_ = true;
|
||||
@ -664,16 +664,15 @@ void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
|
||||
Literal* lit_key = key()->AsLiteral();
|
||||
ASSERT(lit_key != NULL && lit_key->handle()->IsString());
|
||||
Handle<String> name = Handle<String>::cast(lit_key->handle());
|
||||
ZoneMapList* types = oracle->LoadReceiverTypes(this, name);
|
||||
receiver_types_ = types;
|
||||
oracle->LoadReceiverTypes(this, name, &receiver_types_);
|
||||
}
|
||||
} else if (oracle->LoadIsBuiltin(this, Builtins::kKeyedLoadIC_String)) {
|
||||
is_string_access_ = true;
|
||||
} else if (is_monomorphic_) {
|
||||
monomorphic_receiver_type_ = oracle->LoadMonomorphicReceiverType(this);
|
||||
receiver_types_.Add(oracle->LoadMonomorphicReceiverType(this));
|
||||
} else if (oracle->LoadIsMegamorphicWithTypeInfo(this)) {
|
||||
receiver_types_ = new ZoneMapList(kMaxKeyedPolymorphism);
|
||||
oracle->CollectKeyedReceiverTypes(this->id(), receiver_types_);
|
||||
receiver_types_.Reserve(kMaxKeyedPolymorphism);
|
||||
oracle->CollectKeyedReceiverTypes(this->id(), &receiver_types_);
|
||||
}
|
||||
}
|
||||
|
||||
@ -682,30 +681,31 @@ void Assignment::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
|
||||
Property* prop = target()->AsProperty();
|
||||
ASSERT(prop != NULL);
|
||||
is_monomorphic_ = oracle->StoreIsMonomorphicNormal(this);
|
||||
receiver_types_.Clear();
|
||||
if (prop->key()->IsPropertyName()) {
|
||||
Literal* lit_key = prop->key()->AsLiteral();
|
||||
ASSERT(lit_key != NULL && lit_key->handle()->IsString());
|
||||
Handle<String> name = Handle<String>::cast(lit_key->handle());
|
||||
ZoneMapList* types = oracle->StoreReceiverTypes(this, name);
|
||||
receiver_types_ = types;
|
||||
oracle->StoreReceiverTypes(this, name, &receiver_types_);
|
||||
} else if (is_monomorphic_) {
|
||||
// Record receiver type for monomorphic keyed stores.
|
||||
monomorphic_receiver_type_ = oracle->StoreMonomorphicReceiverType(this);
|
||||
receiver_types_.Add(oracle->StoreMonomorphicReceiverType(this));
|
||||
} else if (oracle->StoreIsMegamorphicWithTypeInfo(this)) {
|
||||
receiver_types_ = new ZoneMapList(kMaxKeyedPolymorphism);
|
||||
oracle->CollectKeyedReceiverTypes(this->id(), receiver_types_);
|
||||
receiver_types_.Reserve(kMaxKeyedPolymorphism);
|
||||
oracle->CollectKeyedReceiverTypes(this->id(), &receiver_types_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CountOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
|
||||
is_monomorphic_ = oracle->StoreIsMonomorphicNormal(this);
|
||||
receiver_types_.Clear();
|
||||
if (is_monomorphic_) {
|
||||
// Record receiver type for monomorphic keyed stores.
|
||||
monomorphic_receiver_type_ = oracle->StoreMonomorphicReceiverType(this);
|
||||
receiver_types_.Add(oracle->StoreMonomorphicReceiverType(this));
|
||||
} else if (oracle->StoreIsMegamorphicWithTypeInfo(this)) {
|
||||
receiver_types_ = new ZoneMapList(kMaxKeyedPolymorphism);
|
||||
oracle->CollectKeyedReceiverTypes(this->id(), receiver_types_);
|
||||
receiver_types_.Reserve(kMaxKeyedPolymorphism);
|
||||
oracle->CollectKeyedReceiverTypes(this->id(), &receiver_types_);
|
||||
}
|
||||
}
|
||||
|
||||
@ -789,25 +789,24 @@ void Call::RecordTypeFeedback(TypeFeedbackOracle* oracle,
|
||||
Literal* key = property->key()->AsLiteral();
|
||||
ASSERT(key != NULL && key->handle()->IsString());
|
||||
Handle<String> name = Handle<String>::cast(key->handle());
|
||||
receiver_types_ = oracle->CallReceiverTypes(this, name, call_kind);
|
||||
receiver_types_.Clear();
|
||||
oracle->CallReceiverTypes(this, name, call_kind, &receiver_types_);
|
||||
#ifdef DEBUG
|
||||
if (FLAG_enable_slow_asserts) {
|
||||
if (receiver_types_ != NULL) {
|
||||
int length = receiver_types_->length();
|
||||
int length = receiver_types_.length();
|
||||
for (int i = 0; i < length; i++) {
|
||||
Handle<Map> map = receiver_types_->at(i);
|
||||
Handle<Map> map = receiver_types_.at(i);
|
||||
ASSERT(!map.is_null() && *map != NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
is_monomorphic_ = oracle->CallIsMonomorphic(this);
|
||||
check_type_ = oracle->GetCallCheckType(this);
|
||||
if (is_monomorphic_) {
|
||||
Handle<Map> map;
|
||||
if (receiver_types_ != NULL && receiver_types_->length() > 0) {
|
||||
if (receiver_types_.length() > 0) {
|
||||
ASSERT(check_type_ == RECEIVER_MAP_CHECK);
|
||||
map = receiver_types_->at(0);
|
||||
map = receiver_types_.at(0);
|
||||
} else {
|
||||
ASSERT(check_type_ != RECEIVER_MAP_CHECK);
|
||||
holder_ = Handle<JSObject>(
|
||||
|
74
src/ast.h
74
src/ast.h
@ -33,6 +33,7 @@
|
||||
#include "factory.h"
|
||||
#include "jsregexp.h"
|
||||
#include "runtime.h"
|
||||
#include "small-pointer-list.h"
|
||||
#include "token.h"
|
||||
#include "variables.h"
|
||||
|
||||
@ -207,6 +208,36 @@ class Statement: public AstNode {
|
||||
};
|
||||
|
||||
|
||||
class SmallMapList {
|
||||
public:
|
||||
SmallMapList() {}
|
||||
explicit SmallMapList(int capacity) : list_(capacity) {}
|
||||
|
||||
void Reserve(int capacity) { list_.Reserve(capacity); }
|
||||
void Clear() { list_.Clear(); }
|
||||
|
||||
bool is_empty() const { return list_.is_empty(); }
|
||||
int length() const { return list_.length(); }
|
||||
|
||||
void Add(Handle<Map> handle) {
|
||||
list_.Add(handle.location());
|
||||
}
|
||||
|
||||
Handle<Map> at(int i) const {
|
||||
return Handle<Map>(list_.at(i));
|
||||
}
|
||||
|
||||
Handle<Map> first() const { return at(0); }
|
||||
Handle<Map> last() const { return at(length() - 1); }
|
||||
|
||||
private:
|
||||
// The list stores pointers to Map*, that is Map**, so it's GC safe.
|
||||
SmallPointerList<Map*> list_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(SmallMapList);
|
||||
};
|
||||
|
||||
|
||||
class Expression: public AstNode {
|
||||
public:
|
||||
enum Context {
|
||||
@ -265,13 +296,15 @@ class Expression: public AstNode {
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
virtual ZoneMapList* GetReceiverTypes() {
|
||||
virtual SmallMapList* GetReceiverTypes() {
|
||||
UNREACHABLE();
|
||||
return NULL;
|
||||
}
|
||||
virtual Handle<Map> GetMonomorphicReceiverType() {
|
||||
UNREACHABLE();
|
||||
return Handle<Map>();
|
||||
Handle<Map> GetMonomorphicReceiverType() {
|
||||
ASSERT(IsMonomorphic());
|
||||
SmallMapList* types = GetReceiverTypes();
|
||||
ASSERT(types != NULL && types->length() == 1);
|
||||
return types->at(0);
|
||||
}
|
||||
|
||||
unsigned id() const { return id_; }
|
||||
@ -1213,7 +1246,6 @@ class Property: public Expression {
|
||||
key_(key),
|
||||
pos_(pos),
|
||||
type_(type),
|
||||
receiver_types_(NULL),
|
||||
is_monomorphic_(false),
|
||||
is_array_length_(false),
|
||||
is_string_length_(false),
|
||||
@ -1237,11 +1269,8 @@ class Property: public Expression {
|
||||
// Type feedback information.
|
||||
void RecordTypeFeedback(TypeFeedbackOracle* oracle);
|
||||
virtual bool IsMonomorphic() { return is_monomorphic_; }
|
||||
virtual ZoneMapList* GetReceiverTypes() { return receiver_types_; }
|
||||
virtual SmallMapList* GetReceiverTypes() { return &receiver_types_; }
|
||||
virtual bool IsArrayLength() { return is_array_length_; }
|
||||
virtual Handle<Map> GetMonomorphicReceiverType() {
|
||||
return monomorphic_receiver_type_;
|
||||
}
|
||||
|
||||
private:
|
||||
Expression* obj_;
|
||||
@ -1249,13 +1278,12 @@ class Property: public Expression {
|
||||
int pos_;
|
||||
Type type_;
|
||||
|
||||
ZoneMapList* receiver_types_;
|
||||
SmallMapList receiver_types_;
|
||||
bool is_monomorphic_ : 1;
|
||||
bool is_array_length_ : 1;
|
||||
bool is_string_length_ : 1;
|
||||
bool is_string_access_ : 1;
|
||||
bool is_function_prototype_ : 1;
|
||||
Handle<Map> monomorphic_receiver_type_;
|
||||
};
|
||||
|
||||
|
||||
@ -1271,7 +1299,6 @@ class Call: public Expression {
|
||||
pos_(pos),
|
||||
is_monomorphic_(false),
|
||||
check_type_(RECEIVER_MAP_CHECK),
|
||||
receiver_types_(NULL),
|
||||
return_id_(GetNextId(isolate)) {
|
||||
}
|
||||
|
||||
@ -1285,7 +1312,7 @@ class Call: public Expression {
|
||||
|
||||
void RecordTypeFeedback(TypeFeedbackOracle* oracle,
|
||||
CallKind call_kind);
|
||||
virtual ZoneMapList* GetReceiverTypes() { return receiver_types_; }
|
||||
virtual SmallMapList* GetReceiverTypes() { return &receiver_types_; }
|
||||
virtual bool IsMonomorphic() { return is_monomorphic_; }
|
||||
CheckType check_type() const { return check_type_; }
|
||||
Handle<JSFunction> target() { return target_; }
|
||||
@ -1310,7 +1337,7 @@ class Call: public Expression {
|
||||
|
||||
bool is_monomorphic_;
|
||||
CheckType check_type_;
|
||||
ZoneMapList* receiver_types_;
|
||||
SmallMapList receiver_types_;
|
||||
Handle<JSFunction> target_;
|
||||
Handle<JSObject> holder_;
|
||||
Handle<JSGlobalPropertyCell> cell_;
|
||||
@ -1485,8 +1512,7 @@ class CountOperation: public Expression {
|
||||
expression_(expr),
|
||||
pos_(pos),
|
||||
assignment_id_(GetNextId(isolate)),
|
||||
count_id_(GetNextId(isolate)),
|
||||
receiver_types_(NULL) { }
|
||||
count_id_(GetNextId(isolate)) {}
|
||||
|
||||
DECLARE_NODE_TYPE(CountOperation)
|
||||
|
||||
@ -1507,10 +1533,7 @@ class CountOperation: public Expression {
|
||||
|
||||
void RecordTypeFeedback(TypeFeedbackOracle* oracle);
|
||||
virtual bool IsMonomorphic() { return is_monomorphic_; }
|
||||
virtual Handle<Map> GetMonomorphicReceiverType() {
|
||||
return monomorphic_receiver_type_;
|
||||
}
|
||||
virtual ZoneMapList* GetReceiverTypes() { return receiver_types_; }
|
||||
virtual SmallMapList* GetReceiverTypes() { return &receiver_types_; }
|
||||
|
||||
// Bailout support.
|
||||
int AssignmentId() const { return assignment_id_; }
|
||||
@ -1524,8 +1547,7 @@ class CountOperation: public Expression {
|
||||
int pos_;
|
||||
int assignment_id_;
|
||||
int count_id_;
|
||||
Handle<Map> monomorphic_receiver_type_;
|
||||
ZoneMapList* receiver_types_;
|
||||
SmallMapList receiver_types_;
|
||||
};
|
||||
|
||||
|
||||
@ -1673,10 +1695,7 @@ class Assignment: public Expression {
|
||||
// Type feedback information.
|
||||
void RecordTypeFeedback(TypeFeedbackOracle* oracle);
|
||||
virtual bool IsMonomorphic() { return is_monomorphic_; }
|
||||
virtual ZoneMapList* GetReceiverTypes() { return receiver_types_; }
|
||||
virtual Handle<Map> GetMonomorphicReceiverType() {
|
||||
return monomorphic_receiver_type_;
|
||||
}
|
||||
virtual SmallMapList* GetReceiverTypes() { return &receiver_types_; }
|
||||
|
||||
// Bailout support.
|
||||
int CompoundLoadId() const { return compound_load_id_; }
|
||||
@ -1695,8 +1714,7 @@ class Assignment: public Expression {
|
||||
bool block_end_;
|
||||
|
||||
bool is_monomorphic_;
|
||||
ZoneMapList* receiver_types_;
|
||||
Handle<Map> monomorphic_receiver_type_;
|
||||
SmallMapList receiver_types_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1306,7 +1306,7 @@ void HLoadNamedField::PrintDataTo(StringStream* stream) {
|
||||
|
||||
HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* context,
|
||||
HValue* object,
|
||||
ZoneMapList* types,
|
||||
SmallMapList* types,
|
||||
Handle<String> name)
|
||||
: types_(Min(types->length(), kMaxLoadPolymorphism)),
|
||||
name_(name),
|
||||
|
@ -3405,12 +3405,12 @@ class HLoadNamedFieldPolymorphic: public HTemplateInstruction<2> {
|
||||
public:
|
||||
HLoadNamedFieldPolymorphic(HValue* context,
|
||||
HValue* object,
|
||||
ZoneMapList* types,
|
||||
SmallMapList* types,
|
||||
Handle<String> name);
|
||||
|
||||
HValue* context() { return OperandAt(0); }
|
||||
HValue* object() { return OperandAt(1); }
|
||||
ZoneMapList* types() { return &types_; }
|
||||
SmallMapList* types() { return &types_; }
|
||||
Handle<String> name() { return name_; }
|
||||
bool need_generic() { return need_generic_; }
|
||||
|
||||
@ -3428,7 +3428,7 @@ class HLoadNamedFieldPolymorphic: public HTemplateInstruction<2> {
|
||||
virtual bool DataEquals(HValue* value);
|
||||
|
||||
private:
|
||||
ZoneMapList types_;
|
||||
SmallMapList types_;
|
||||
Handle<String> name_;
|
||||
bool need_generic_;
|
||||
};
|
||||
|
@ -3395,7 +3395,7 @@ HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
|
||||
ASSERT(!name.is_null());
|
||||
|
||||
LookupResult lookup;
|
||||
ZoneMapList* types = expr->GetReceiverTypes();
|
||||
SmallMapList* types = expr->GetReceiverTypes();
|
||||
bool is_monomorphic = expr->IsMonomorphic() &&
|
||||
ComputeStoredField(types->first(), name, &lookup);
|
||||
|
||||
@ -3409,7 +3409,7 @@ HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
|
||||
void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
|
||||
HValue* object,
|
||||
HValue* value,
|
||||
ZoneMapList* types,
|
||||
SmallMapList* types,
|
||||
Handle<String> name) {
|
||||
// TODO(ager): We should recognize when the prototype chains for different
|
||||
// maps are identical. In that case we can avoid repeatedly generating the
|
||||
@ -3500,7 +3500,7 @@ void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
|
||||
Handle<String> name = Handle<String>::cast(key->handle());
|
||||
ASSERT(!name.is_null());
|
||||
|
||||
ZoneMapList* types = expr->GetReceiverTypes();
|
||||
SmallMapList* types = expr->GetReceiverTypes();
|
||||
LookupResult lookup;
|
||||
|
||||
if (expr->IsMonomorphic()) {
|
||||
@ -3986,7 +3986,7 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
|
||||
*has_side_effects = false;
|
||||
AddInstruction(new(zone()) HCheckNonSmi(object));
|
||||
AddInstruction(HCheckInstanceType::NewIsSpecObject(object));
|
||||
ZoneMapList* maps = prop->GetReceiverTypes();
|
||||
SmallMapList* maps = prop->GetReceiverTypes();
|
||||
bool todo_external_array = false;
|
||||
|
||||
static const int kNumElementTypes = JSObject::kElementsKindCount;
|
||||
@ -4260,7 +4260,7 @@ void HGraphBuilder::VisitProperty(Property* expr) {
|
||||
|
||||
} else if (expr->key()->IsPropertyName()) {
|
||||
Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
|
||||
ZoneMapList* types = expr->GetReceiverTypes();
|
||||
SmallMapList* types = expr->GetReceiverTypes();
|
||||
|
||||
HValue* obj = Pop();
|
||||
if (expr->IsMonomorphic()) {
|
||||
@ -4321,7 +4321,7 @@ void HGraphBuilder::AddCheckConstantFunction(Call* expr,
|
||||
|
||||
void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
|
||||
HValue* receiver,
|
||||
ZoneMapList* types,
|
||||
SmallMapList* types,
|
||||
Handle<String> name) {
|
||||
// TODO(ager): We should recognize when the prototype chains for different
|
||||
// maps are identical. In that case we can avoid repeatedly generating the
|
||||
@ -4849,13 +4849,14 @@ void HGraphBuilder::VisitCall(Call* expr) {
|
||||
|
||||
Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
|
||||
|
||||
ZoneMapList* types = expr->GetReceiverTypes();
|
||||
SmallMapList* types = expr->GetReceiverTypes();
|
||||
|
||||
HValue* receiver =
|
||||
environment()->ExpressionStackAt(expr->arguments()->length());
|
||||
if (expr->IsMonomorphic()) {
|
||||
Handle<Map> receiver_map =
|
||||
(types == NULL) ? Handle<Map>::null() : types->first();
|
||||
Handle<Map> receiver_map = (types == NULL || types->is_empty())
|
||||
? Handle<Map>::null()
|
||||
: types->first();
|
||||
if (TryInlineBuiltinFunction(expr,
|
||||
receiver,
|
||||
receiver_map,
|
||||
|
@ -901,11 +901,11 @@ class HGraphBuilder: public AstVisitor {
|
||||
void HandlePolymorphicStoreNamedField(Assignment* expr,
|
||||
HValue* object,
|
||||
HValue* value,
|
||||
ZoneMapList* types,
|
||||
SmallMapList* types,
|
||||
Handle<String> name);
|
||||
void HandlePolymorphicCallNamed(Call* expr,
|
||||
HValue* receiver,
|
||||
ZoneMapList* types,
|
||||
SmallMapList* types,
|
||||
Handle<String> name);
|
||||
void HandleLiteralCompareTypeof(CompareOperation* compare_expr,
|
||||
Expression* expr,
|
||||
|
@ -44,6 +44,31 @@ class SmallPointerList {
|
||||
public:
|
||||
SmallPointerList() : data_(kEmptyTag) {}
|
||||
|
||||
explicit SmallPointerList(int capacity) : data_(kEmptyTag) {
|
||||
Reserve(capacity);
|
||||
}
|
||||
|
||||
void Reserve(int capacity) {
|
||||
if (capacity < 2) return;
|
||||
if ((data_ & kTagMask) == kListTag) {
|
||||
if (list()->capacity() >= capacity) return;
|
||||
int old_length = list()->length();
|
||||
list()->AddBlock(NULL, capacity - list()->capacity());
|
||||
list()->Rewind(old_length);
|
||||
return;
|
||||
}
|
||||
PointerList* list = new PointerList(capacity);
|
||||
if ((data_ & kTagMask) == kSingletonTag) {
|
||||
list->Add(single_value());
|
||||
}
|
||||
ASSERT(IsAligned(reinterpret_cast<intptr_t>(list), kPointerAlignment));
|
||||
data_ = reinterpret_cast<intptr_t>(list) | kListTag;
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
data_ = kEmptyTag;
|
||||
}
|
||||
|
||||
bool is_empty() const { return length() == 0; }
|
||||
|
||||
int length() const {
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
#include "api.h"
|
||||
#include "arguments.h"
|
||||
#include "ast.h"
|
||||
#include "code-stubs.h"
|
||||
#include "gdb-jit.h"
|
||||
#include "ic-inl.h"
|
||||
@ -1161,7 +1162,7 @@ void StubCache::Clear() {
|
||||
}
|
||||
|
||||
|
||||
void StubCache::CollectMatchingMaps(ZoneMapList* types,
|
||||
void StubCache::CollectMatchingMaps(SmallMapList* types,
|
||||
String* name,
|
||||
Code::Flags flags) {
|
||||
for (int i = 0; i < kPrimaryTableSize; i++) {
|
||||
|
@ -46,8 +46,10 @@ namespace internal {
|
||||
// invalidate the cache whenever a prototype map is changed. The stub
|
||||
// validates the map chain as in the mono-morphic case.
|
||||
|
||||
class SmallMapList;
|
||||
class StubCache;
|
||||
|
||||
|
||||
class SCTableReference {
|
||||
public:
|
||||
Address address() const { return address_; }
|
||||
@ -294,7 +296,7 @@ class StubCache {
|
||||
void Clear();
|
||||
|
||||
// Collect all maps that match the name and flags.
|
||||
void CollectMatchingMaps(ZoneMapList* types,
|
||||
void CollectMatchingMaps(SmallMapList* types,
|
||||
String* name,
|
||||
Code::Flags flags);
|
||||
|
||||
|
@ -159,23 +159,26 @@ Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType(Expression* expr) {
|
||||
}
|
||||
|
||||
|
||||
ZoneMapList* TypeFeedbackOracle::LoadReceiverTypes(Property* expr,
|
||||
Handle<String> name) {
|
||||
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL);
|
||||
return CollectReceiverTypes(expr->id(), name, flags);
|
||||
}
|
||||
|
||||
|
||||
ZoneMapList* TypeFeedbackOracle::StoreReceiverTypes(Assignment* expr,
|
||||
Handle<String> name) {
|
||||
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, NORMAL);
|
||||
return CollectReceiverTypes(expr->id(), name, flags);
|
||||
}
|
||||
|
||||
|
||||
ZoneMapList* TypeFeedbackOracle::CallReceiverTypes(Call* expr,
|
||||
void TypeFeedbackOracle::LoadReceiverTypes(Property* expr,
|
||||
Handle<String> name,
|
||||
CallKind call_kind) {
|
||||
SmallMapList* types) {
|
||||
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL);
|
||||
CollectReceiverTypes(expr->id(), name, flags, types);
|
||||
}
|
||||
|
||||
|
||||
void TypeFeedbackOracle::StoreReceiverTypes(Assignment* expr,
|
||||
Handle<String> name,
|
||||
SmallMapList* types) {
|
||||
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, NORMAL);
|
||||
CollectReceiverTypes(expr->id(), name, flags, types);
|
||||
}
|
||||
|
||||
|
||||
void TypeFeedbackOracle::CallReceiverTypes(Call* expr,
|
||||
Handle<String> name,
|
||||
CallKind call_kind,
|
||||
SmallMapList* types) {
|
||||
int arity = expr->arguments()->length();
|
||||
|
||||
// Note: Currently we do not take string extra ic data into account
|
||||
@ -189,7 +192,7 @@ ZoneMapList* TypeFeedbackOracle::CallReceiverTypes(Call* expr,
|
||||
OWN_MAP,
|
||||
NOT_IN_LOOP,
|
||||
arity);
|
||||
return CollectReceiverTypes(expr->id(), name, flags);
|
||||
CollectReceiverTypes(expr->id(), name, flags, types);
|
||||
}
|
||||
|
||||
|
||||
@ -391,36 +394,30 @@ TypeInfo TypeFeedbackOracle::IncrementType(CountOperation* expr) {
|
||||
}
|
||||
|
||||
|
||||
ZoneMapList* TypeFeedbackOracle::CollectReceiverTypes(unsigned ast_id,
|
||||
void TypeFeedbackOracle::CollectReceiverTypes(unsigned ast_id,
|
||||
Handle<String> name,
|
||||
Code::Flags flags) {
|
||||
Code::Flags flags,
|
||||
SmallMapList* types) {
|
||||
Isolate* isolate = Isolate::Current();
|
||||
Handle<Object> object = GetInfo(ast_id);
|
||||
if (object->IsUndefined() || object->IsSmi()) return NULL;
|
||||
if (object->IsUndefined() || object->IsSmi()) return;
|
||||
|
||||
if (*object == isolate->builtins()->builtin(Builtins::kStoreIC_GlobalProxy)) {
|
||||
// TODO(fschneider): We could collect the maps and signal that
|
||||
// we need a generic store (or load) here.
|
||||
ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC);
|
||||
return NULL;
|
||||
} else if (object->IsMap()) {
|
||||
ZoneMapList* types = new ZoneMapList(1);
|
||||
types->Add(Handle<Map>::cast(object));
|
||||
return types;
|
||||
} else if (Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC) {
|
||||
ZoneMapList* types = new ZoneMapList(4);
|
||||
types->Reserve(4);
|
||||
ASSERT(object->IsCode());
|
||||
isolate->stub_cache()->CollectMatchingMaps(types, *name, flags);
|
||||
return types->length() > 0 ? types : NULL;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TypeFeedbackOracle::CollectKeyedReceiverTypes(
|
||||
unsigned ast_id,
|
||||
ZoneMapList* types) {
|
||||
void TypeFeedbackOracle::CollectKeyedReceiverTypes(unsigned ast_id,
|
||||
SmallMapList* types) {
|
||||
Handle<Object> object = GetInfo(ast_id);
|
||||
if (!object->IsCode()) return;
|
||||
Handle<Code> code = Handle<Code>::cast(object);
|
||||
|
@ -203,14 +203,16 @@ enum StringStubFeedback {
|
||||
|
||||
// Forward declarations.
|
||||
class Assignment;
|
||||
class UnaryOperation;
|
||||
class BinaryOperation;
|
||||
class Call;
|
||||
class CompareOperation;
|
||||
class CountOperation;
|
||||
class CompilationInfo;
|
||||
class Property;
|
||||
class CaseClause;
|
||||
class CompareOperation;
|
||||
class CompilationInfo;
|
||||
class CountOperation;
|
||||
class Property;
|
||||
class SmallMapList;
|
||||
class UnaryOperation;
|
||||
|
||||
|
||||
class TypeFeedbackOracle BASE_EMBEDDED {
|
||||
public:
|
||||
@ -225,13 +227,18 @@ class TypeFeedbackOracle BASE_EMBEDDED {
|
||||
Handle<Map> LoadMonomorphicReceiverType(Property* expr);
|
||||
Handle<Map> StoreMonomorphicReceiverType(Expression* expr);
|
||||
|
||||
ZoneMapList* LoadReceiverTypes(Property* expr, Handle<String> name);
|
||||
ZoneMapList* StoreReceiverTypes(Assignment* expr, Handle<String> name);
|
||||
ZoneMapList* CallReceiverTypes(Call* expr,
|
||||
void LoadReceiverTypes(Property* expr,
|
||||
Handle<String> name,
|
||||
CallKind call_kind);
|
||||
SmallMapList* types);
|
||||
void StoreReceiverTypes(Assignment* expr,
|
||||
Handle<String> name,
|
||||
SmallMapList* types);
|
||||
void CallReceiverTypes(Call* expr,
|
||||
Handle<String> name,
|
||||
CallKind call_kind,
|
||||
SmallMapList* types);
|
||||
void CollectKeyedReceiverTypes(unsigned ast_id,
|
||||
ZoneMapList* types);
|
||||
SmallMapList* types);
|
||||
|
||||
CheckType GetCallCheckType(Call* expr);
|
||||
Handle<JSObject> GetPrototypeForPrimitiveCheck(CheckType check);
|
||||
@ -252,9 +259,10 @@ class TypeFeedbackOracle BASE_EMBEDDED {
|
||||
TypeInfo IncrementType(CountOperation* expr);
|
||||
|
||||
private:
|
||||
ZoneMapList* CollectReceiverTypes(unsigned ast_id,
|
||||
void CollectReceiverTypes(unsigned ast_id,
|
||||
Handle<String> name,
|
||||
Code::Flags flags);
|
||||
Code::Flags flags,
|
||||
SmallMapList* types);
|
||||
|
||||
void SetInfo(unsigned ast_id, Object* target);
|
||||
|
||||
|
@ -200,10 +200,6 @@ class ZoneList: public List<T, ZoneListAllocationPolicy> {
|
||||
};
|
||||
|
||||
|
||||
// Introduce a convenience type for zone lists of map handles.
|
||||
typedef ZoneList<Handle<Map> > ZoneMapList;
|
||||
|
||||
|
||||
// ZoneScopes keep track of the current parsing and compilation
|
||||
// nesting and cleans up generated ASTs in the Zone when exiting the
|
||||
// outer-most scope.
|
||||
|
Loading…
Reference in New Issue
Block a user