Stop using HeapType in IC and Crankshaft

BUG=

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

Cr-Commit-Position: refs/heads/master@{#26696}
This commit is contained in:
verwaest 2015-02-17 07:33:26 -08:00 committed by Commit bot
parent 0a4047a69b
commit 119cb56617
25 changed files with 396 additions and 530 deletions

View File

@ -69,20 +69,10 @@ static V8_INLINE bool CheckForName(Handle<Name> name,
// Returns true for properties that are accessors to object fields.
// If true, *object_offset contains offset of object field.
template <class T>
bool Accessors::IsJSObjectFieldAccessor(typename T::TypeHandle type,
Handle<Name> name,
bool Accessors::IsJSObjectFieldAccessor(Handle<Map> map, Handle<Name> name,
int* object_offset) {
Isolate* isolate = name->GetIsolate();
if (type->Is(T::String())) {
return CheckForName(name, isolate->factory()->length_string(),
String::kLengthOffset, object_offset);
}
if (!type->IsClass()) return false;
Handle<Map> map = type->AsClass()->Map();
switch (map->instance_type()) {
case JS_ARRAY_TYPE:
return
@ -107,23 +97,16 @@ bool Accessors::IsJSObjectFieldAccessor(typename T::TypeHandle type,
CheckForName(name, isolate->factory()->byte_offset_string(),
JSDataView::kByteOffsetOffset, object_offset);
default:
if (map->instance_type() < FIRST_NONSTRING_TYPE) {
return CheckForName(name, isolate->factory()->length_string(),
String::kLengthOffset, object_offset);
}
return false;
}
}
template
bool Accessors::IsJSObjectFieldAccessor<Type>(Type* type,
Handle<Name> name,
int* object_offset);
template
bool Accessors::IsJSObjectFieldAccessor<HeapType>(Handle<HeapType> type,
Handle<Name> name,
int* object_offset);
bool SetPropertyOnInstanceIfInherited(
Isolate* isolate, const v8::PropertyCallbackInfo<void>& info,
v8::Local<v8::Name> name, Handle<Object> value) {

View File

@ -78,9 +78,7 @@ class Accessors : public AllStatic {
// Returns true for properties that are accessors to object fields.
// If true, *object_offset contains offset of object field.
template <class T>
static bool IsJSObjectFieldAccessor(typename T::TypeHandle type,
Handle<Name> name,
static bool IsJSObjectFieldAccessor(Handle<Map> map, Handle<Name> name,
int* object_offset);
static Handle<AccessorInfo> MakeAccessor(

View File

@ -4472,11 +4472,6 @@ void HOptimizedGraphBuilder::SetUpScope(Scope* scope) {
}
Type* HOptimizedGraphBuilder::ToType(Handle<Map> map) {
return IC::MapToType<Type>(map, zone());
}
void HOptimizedGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) {
for (int i = 0; i < statements->length(); i++) {
Statement* stmt = statements->at(i);
@ -5445,10 +5440,9 @@ void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
}
static bool CanInlinePropertyAccess(Type* type) {
if (type->Is(Type::NumberOrString())) return true;
if (!type->IsClass()) return false;
Handle<Map> map = type->AsClass()->Map();
static bool CanInlinePropertyAccess(Handle<Map> map) {
if (map->instance_type() == HEAP_NUMBER_TYPE) return true;
if (map->instance_type() < FIRST_NONSTRING_TYPE) return true;
return map->IsJSObjectMap() &&
!map->is_dictionary_map() &&
!map->has_named_interceptor();
@ -5618,7 +5612,7 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
CHECK_ALIVE(store = BuildNamedGeneric(
STORE, NULL, literal, name, value));
} else {
PropertyAccessInfo info(this, STORE, ToType(map), name);
PropertyAccessInfo info(this, STORE, map, name);
if (info.CanAccessMonomorphic()) {
HValue* checked_literal = Add<HCheckMaps>(literal, map);
DCHECK(!info.IsAccessorConstant());
@ -5907,20 +5901,16 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible(
PropertyAccessInfo* info) {
if (!CanInlinePropertyAccess(type_)) return false;
if (!CanInlinePropertyAccess(map_)) return false;
// Currently only handle Type::Number as a polymorphic case.
// TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
// instruction.
if (type_->Is(Type::Number())) return false;
if (IsNumberType()) return false;
// Values are only compatible for monomorphic load if they all behave the same
// regarding value wrappers.
if (type_->Is(Type::NumberOrString())) {
if (!info->type_->Is(Type::NumberOrString())) return false;
} else {
if (info->type_->Is(Type::NumberOrString())) return false;
}
if (IsValueWrapped() != info->IsValueWrapped()) return false;
if (!LookupDescriptor()) return false;
@ -5979,9 +5969,9 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible(
bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() {
if (!type_->IsClass()) return true;
map()->LookupDescriptor(NULL, *name_, &lookup_);
return LoadResult(map());
if (!map_->IsJSObjectMap()) return true;
map_->LookupDescriptor(NULL, *name_, &lookup_);
return LoadResult(map_);
}
@ -6009,9 +5999,8 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) {
CallOptimization call_optimization(accessor);
if (call_optimization.is_simple_api_call()) {
CallOptimization::HolderLookup holder_lookup;
Handle<Map> receiver_map = this->map();
api_holder_ = call_optimization.LookupHolderOfExpectedType(
receiver_map, &holder_lookup);
api_holder_ =
call_optimization.LookupHolderOfExpectedType(map_, &holder_lookup);
}
}
accessor_ = accessor;
@ -6069,7 +6058,7 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() {
JSObject::TryMigrateInstance(holder_);
}
map = Handle<Map>(holder_->map());
if (!CanInlinePropertyAccess(ToType(map))) {
if (!CanInlinePropertyAccess(map)) {
lookup_.NotFound();
return false;
}
@ -6082,10 +6071,9 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() {
bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() {
if (!CanInlinePropertyAccess(type_)) return false;
if (!CanInlinePropertyAccess(map_)) return false;
if (IsJSObjectFieldAccessor()) return IsLoad();
if (this->map()->function_with_prototype() &&
!this->map()->has_non_instance_prototype() &&
if (map_->function_with_prototype() && !map_->has_non_instance_prototype() &&
name_.is_identical_to(isolate()->factory()->prototype_string())) {
return IsLoad();
}
@ -6095,18 +6083,17 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() {
if (IsLoad()) return true;
if (IsAccessorConstant()) return true;
Handle<Map> map = this->map();
map->LookupTransition(NULL, *name_, NONE, &lookup_);
if (lookup_.IsTransitionToData() && map->unused_property_fields() > 0) {
map_->LookupTransition(NULL, *name_, NONE, &lookup_);
if (lookup_.IsTransitionToData() && map_->unused_property_fields() > 0) {
// Construct the object field access.
int descriptor = transition()->LastAdded();
int index =
transition()->instance_descriptors()->GetFieldIndex(descriptor) -
map->inobject_properties();
map_->inobject_properties();
PropertyDetails details =
transition()->instance_descriptors()->GetDetails(descriptor);
Representation representation = details.representation();
access_ = HObjectAccess::ForField(map, index, representation, name_);
access_ = HObjectAccess::ForField(map_, index, representation, name_);
// Load field map for heap objects.
LoadFieldMaps(transition());
@ -6117,17 +6104,16 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() {
bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic(
SmallMapList* types) {
DCHECK(type_->Is(ToType(types->first())));
SmallMapList* maps) {
DCHECK(map_.is_identical_to(maps->first()));
if (!CanAccessMonomorphic()) return false;
STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
if (types->length() > kMaxLoadPolymorphism) return false;
if (maps->length() > kMaxLoadPolymorphism) return false;
HObjectAccess access = HObjectAccess::ForMap(); // bogus default
if (GetJSObjectFieldAccess(&access)) {
for (int i = 1; i < types->length(); ++i) {
PropertyAccessInfo test_info(
builder_, access_type_, ToType(types->at(i)), name_);
for (int i = 1; i < maps->length(); ++i) {
PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_);
HObjectAccess test_access = HObjectAccess::ForMap(); // bogus default
if (!test_info.GetJSObjectFieldAccess(&test_access)) return false;
if (!access.Equals(test_access)) return false;
@ -6135,18 +6121,17 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic(
return true;
}
// Currently only handle Type::Number as a polymorphic case.
// Currently only handle numbers as a polymorphic case.
// TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
// instruction.
if (type_->Is(Type::Number())) return false;
if (IsNumberType()) return false;
// Multiple maps cannot transition to the same target map.
DCHECK(!IsLoad() || !IsTransition());
if (IsTransition() && types->length() > 1) return false;
if (IsTransition() && maps->length() > 1) return false;
for (int i = 1; i < types->length(); ++i) {
PropertyAccessInfo test_info(
builder_, access_type_, ToType(types->at(i)), name_);
for (int i = 1; i < maps->length(); ++i) {
PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_);
if (!test_info.IsCompatible(this)) return false;
}
@ -6156,19 +6141,25 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic(
Handle<Map> HOptimizedGraphBuilder::PropertyAccessInfo::map() {
JSFunction* ctor = IC::GetRootConstructor(
type_, current_info()->closure()->context()->native_context());
*map_, current_info()->closure()->context()->native_context());
if (ctor != NULL) return handle(ctor->initial_map());
return type_->AsClass()->Map();
return map_;
}
static bool NeedsWrappingFor(Type* type, Handle<JSFunction> target) {
return type->Is(Type::NumberOrString()) &&
static bool NeedsWrapping(Handle<Map> map, Handle<JSFunction> target) {
return !map->IsJSObjectMap() &&
is_sloppy(target->shared()->language_mode()) &&
!target->shared()->native();
}
bool HOptimizedGraphBuilder::PropertyAccessInfo::NeedsWrappingFor(
Handle<JSFunction> target) const {
return NeedsWrapping(map_, target);
}
HInstruction* HOptimizedGraphBuilder::BuildMonomorphicAccess(
PropertyAccessInfo* info,
HValue* object,
@ -6222,7 +6213,7 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicAccess(
Push(value);
}
if (NeedsWrappingFor(info->type(), info->accessor())) {
if (info->NeedsWrappingFor(info->accessor())) {
HValue* function = Add<HConstant>(info->accessor());
PushArgumentsFromEnvironment(argument_count);
return New<HCallFunction>(function, argument_count, WRAP_AND_CALL);
@ -6248,13 +6239,8 @@ HInstruction* HOptimizedGraphBuilder::BuildMonomorphicAccess(
void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess(
PropertyAccessType access_type,
Expression* expr,
BailoutId ast_id,
BailoutId return_id,
HValue* object,
HValue* value,
SmallMapList* types,
PropertyAccessType access_type, Expression* expr, BailoutId ast_id,
BailoutId return_id, HValue* object, HValue* value, SmallMapList* maps,
Handle<String> name) {
// Something did not match; must use a polymorphic load.
int count = 0;
@ -6265,33 +6251,33 @@ void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess(
bool handle_smi = false;
STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
int i;
for (i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
PropertyAccessInfo info(this, access_type, ToType(types->at(i)), name);
if (info.type()->Is(Type::String())) {
for (i = 0; i < maps->length() && count < kMaxLoadPolymorphism; ++i) {
PropertyAccessInfo info(this, access_type, maps->at(i), name);
if (info.IsStringType()) {
if (handled_string) continue;
handled_string = true;
}
if (info.CanAccessMonomorphic()) {
count++;
if (info.type()->Is(Type::Number())) {
if (info.IsNumberType()) {
handle_smi = true;
break;
}
}
}
if (i < types->length()) {
if (i < maps->length()) {
count = -1;
types->Clear();
maps->Clear();
} else {
count = 0;
}
HControlInstruction* smi_check = NULL;
handled_string = false;
for (i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
PropertyAccessInfo info(this, access_type, ToType(types->at(i)), name);
if (info.type()->Is(Type::String())) {
for (i = 0; i < maps->length() && count < kMaxLoadPolymorphism; ++i) {
PropertyAccessInfo info(this, access_type, maps->at(i), name);
if (info.IsStringType()) {
if (handled_string) continue;
handled_string = true;
}
@ -6318,11 +6304,11 @@ void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess(
HUnaryControlInstruction* compare;
HValue* dependency;
if (info.type()->Is(Type::Number())) {
if (info.IsNumberType()) {
Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
compare = New<HCompareMap>(object, heap_number_map, if_true, if_false);
dependency = smi_check;
} else if (info.type()->Is(Type::String())) {
} else if (info.IsStringType()) {
compare = New<HIsStringAndBranch>(object, if_true, if_false);
dependency = compare;
} else {
@ -6331,7 +6317,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess(
}
FinishCurrentBlock(compare);
if (info.type()->Is(Type::Number())) {
if (info.IsNumberType()) {
GotoNoSimulate(if_true, number_block);
if_true = number_block;
}
@ -6366,7 +6352,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess(
// Finish up. Unconditionally deoptimize if we've handled all the maps we
// know about and do not want to handle ones we've never seen. Otherwise
// use a generic IC.
if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
if (count == maps->length() && FLAG_deoptimize_uncommon_cases) {
FinishExitWithHardDeoptimization(
Deoptimizer::kUnknownMapInPolymorphicAccess);
} else {
@ -6399,22 +6385,21 @@ static bool ComputeReceiverTypes(Expression* expr,
HValue* receiver,
SmallMapList** t,
Zone* zone) {
SmallMapList* types = expr->GetReceiverTypes();
*t = types;
SmallMapList* maps = expr->GetReceiverTypes();
*t = maps;
bool monomorphic = expr->IsMonomorphic();
if (types != NULL && receiver->HasMonomorphicJSObjectType()) {
if (maps != NULL && receiver->HasMonomorphicJSObjectType()) {
Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap();
types->FilterForPossibleTransitions(root_map);
monomorphic = types->length() == 1;
maps->FilterForPossibleTransitions(root_map);
monomorphic = maps->length() == 1;
}
return monomorphic &&
CanInlinePropertyAccess(IC::MapToType<Type>(types->first(), zone));
return monomorphic && CanInlinePropertyAccess(maps->first());
}
static bool AreStringTypes(SmallMapList* types) {
for (int i = 0; i < types->length(); i++) {
if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false;
static bool AreStringTypes(SmallMapList* maps) {
for (int i = 0; i < maps->length(); i++) {
if (maps->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false;
}
return true;
}
@ -7191,8 +7176,8 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
DCHECK(!expr->IsPropertyName());
HInstruction* instr = NULL;
SmallMapList* types;
bool monomorphic = ComputeReceiverTypes(expr, obj, &types, zone());
SmallMapList* maps;
bool monomorphic = ComputeReceiverTypes(expr, obj, &maps, zone());
bool force_generic = false;
if (expr->GetKeyType() == PROPERTY) {
@ -7202,13 +7187,13 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
force_generic = true;
monomorphic = false;
} else if (access_type == STORE &&
(monomorphic || (types != NULL && !types->is_empty()))) {
(monomorphic || (maps != NULL && !maps->is_empty()))) {
// Stores can't be mono/polymorphic if their prototype chain has dictionary
// elements. However a receiver map that has dictionary elements itself
// should be left to normal mono/poly behavior (the other maps may benefit
// from highly optimized stores).
for (int i = 0; i < types->length(); i++) {
Handle<Map> current_map = types->at(i);
for (int i = 0; i < maps->length(); i++) {
Handle<Map> current_map = maps->at(i);
if (current_map->DictionaryElementsInPrototypeChainOnly()) {
force_generic = true;
monomorphic = false;
@ -7216,13 +7201,13 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
}
}
} else if (access_type == LOAD && !monomorphic &&
(types != NULL && !types->is_empty())) {
(maps != NULL && !maps->is_empty())) {
// Polymorphic loads have to go generic if any of the maps are strings.
// If some, but not all of the maps are strings, we should go generic
// because polymorphic access wants to key on ElementsKind and isn't
// compatible with strings.
for (int i = 0; i < types->length(); i++) {
Handle<Map> current_map = types->at(i);
for (int i = 0; i < maps->length(); i++) {
Handle<Map> current_map = maps->at(i);
if (current_map->IsStringMap()) {
force_generic = true;
break;
@ -7231,7 +7216,7 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
}
if (monomorphic) {
Handle<Map> map = types->first();
Handle<Map> map = maps->first();
if (!CanInlineElementAccess(map)) {
instr = AddInstruction(BuildKeyedGeneric(access_type, expr, obj, key,
val));
@ -7240,10 +7225,10 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
instr = BuildMonomorphicElementAccess(
obj, key, val, NULL, map, access_type, expr->GetStoreMode());
}
} else if (!force_generic && (types != NULL && !types->is_empty())) {
return HandlePolymorphicElementAccess(
expr, obj, key, val, types, access_type,
expr->GetStoreMode(), has_side_effects);
} else if (!force_generic && (maps != NULL && !maps->is_empty())) {
return HandlePolymorphicElementAccess(expr, obj, key, val, maps,
access_type, expr->GetStoreMode(),
has_side_effects);
} else {
if (access_type == STORE) {
if (expr->IsAssignment() &&
@ -7352,27 +7337,27 @@ HInstruction* HOptimizedGraphBuilder::BuildNamedAccess(
Handle<String> name,
HValue* value,
bool is_uninitialized) {
SmallMapList* types;
ComputeReceiverTypes(expr, object, &types, zone());
DCHECK(types != NULL);
SmallMapList* maps;
ComputeReceiverTypes(expr, object, &maps, zone());
DCHECK(maps != NULL);
if (types->length() > 0) {
PropertyAccessInfo info(this, access, ToType(types->first()), name);
if (!info.CanAccessAsMonomorphic(types)) {
HandlePolymorphicNamedFieldAccess(
access, expr, ast_id, return_id, object, value, types, name);
if (maps->length() > 0) {
PropertyAccessInfo info(this, access, maps->first(), name);
if (!info.CanAccessAsMonomorphic(maps)) {
HandlePolymorphicNamedFieldAccess(access, expr, ast_id, return_id, object,
value, maps, name);
return NULL;
}
HValue* checked_object;
// Type::Number() is only supported by polymorphic load/call handling.
DCHECK(!info.type()->Is(Type::Number()));
DCHECK(!info.IsNumberType());
BuildCheckHeapObject(object);
if (AreStringTypes(types)) {
if (AreStringTypes(maps)) {
checked_object =
Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING);
} else {
checked_object = Add<HCheckMaps>(object, types);
checked_object = Add<HCheckMaps>(object, maps);
}
return BuildMonomorphicAccess(
&info, object, checked_object, value, ast_id, return_id);
@ -7562,11 +7547,10 @@ inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) {
}
void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
Call* expr,
HValue* receiver,
SmallMapList* types,
Handle<String> name) {
void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
HValue* receiver,
SmallMapList* maps,
Handle<String> name) {
int argument_count = expr->arguments()->length() + 1; // Includes receiver.
FunctionSorter order[kMaxCallPolymorphism];
@ -7575,17 +7559,17 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
int ordered_functions = 0;
int i;
for (i = 0; i < types->length() && ordered_functions < kMaxCallPolymorphism;
for (i = 0; i < maps->length() && ordered_functions < kMaxCallPolymorphism;
++i) {
PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name);
PropertyAccessInfo info(this, LOAD, maps->at(i), name);
if (info.CanAccessMonomorphic() && info.IsDataConstant() &&
info.constant()->IsJSFunction()) {
if (info.type()->Is(Type::String())) {
if (info.IsStringType()) {
if (handled_string) continue;
handled_string = true;
}
Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
if (info.type()->Is(Type::Number())) {
if (info.IsNumberType()) {
handle_smi = true;
}
expr->set_target(target);
@ -7596,8 +7580,8 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
std::sort(order, order + ordered_functions);
if (i < types->length()) {
types->Clear();
if (i < maps->length()) {
maps->Clear();
ordered_functions = -1;
}
@ -7608,8 +7592,8 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
for (int fn = 0; fn < ordered_functions; ++fn) {
int i = order[fn].index();
PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name);
if (info.type()->Is(Type::String())) {
PropertyAccessInfo info(this, LOAD, maps->at(i), name);
if (info.IsStringType()) {
if (handled_string) continue;
handled_string = true;
}
@ -7639,17 +7623,17 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
HUnaryControlInstruction* compare;
Handle<Map> map = info.map();
if (info.type()->Is(Type::Number())) {
if (info.IsNumberType()) {
Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false);
} else if (info.type()->Is(Type::String())) {
} else if (info.IsStringType()) {
compare = New<HIsStringAndBranch>(receiver, if_true, if_false);
} else {
compare = New<HCompareMap>(receiver, map, if_true, if_false);
}
FinishCurrentBlock(compare);
if (info.type()->Is(Type::Number())) {
if (info.IsNumberType()) {
GotoNoSimulate(if_true, number_block);
if_true = number_block;
}
@ -7662,7 +7646,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
environment()->SetExpressionStackAt(0, function);
Push(receiver);
CHECK_ALIVE(VisitExpressions(expr->arguments()));
bool needs_wrapping = NeedsWrappingFor(info.type(), target);
bool needs_wrapping = info.NeedsWrappingFor(target);
bool try_inline = FLAG_polymorphic_inlining && !needs_wrapping;
if (FLAG_trace_inlining && try_inline) {
Handle<JSFunction> caller = current_info()->closure();
@ -7698,7 +7682,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
// Finish up. Unconditionally deoptimize if we've handled all the maps we
// know about and do not want to handle ones we've never seen. Otherwise
// use a generic IC.
if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) {
if (ordered_functions == maps->length() && FLAG_deoptimize_uncommon_cases) {
FinishExitWithHardDeoptimization(Deoptimizer::kUnknownMapInPolymorphicCall);
} else {
Property* prop = expr->expression()->AsProperty();
@ -9135,14 +9119,14 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
CHECK_ALIVE(VisitForValue(prop->obj()));
HValue* receiver = Top();
SmallMapList* types;
ComputeReceiverTypes(expr, receiver, &types, zone());
SmallMapList* maps;
ComputeReceiverTypes(expr, receiver, &maps, zone());
if (prop->key()->IsPropertyName() && types->length() > 0) {
if (prop->key()->IsPropertyName() && maps->length() > 0) {
Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
PropertyAccessInfo info(this, LOAD, ToType(types->first()), name);
if (!info.CanAccessAsMonomorphic(types)) {
HandlePolymorphicCallNamed(expr, receiver, types, name);
PropertyAccessInfo info(this, LOAD, maps->first(), name);
if (!info.CanAccessAsMonomorphic(maps)) {
HandlePolymorphicCallNamed(expr, receiver, maps, name);
return;
}
}
@ -9171,7 +9155,7 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
if (TryIndirectCall(expr)) return;
CHECK_ALIVE(VisitExpressions(expr->arguments()));
Handle<Map> map = types->length() == 1 ? types->first() : Handle<Map>();
Handle<Map> map = maps->length() == 1 ? maps->first() : Handle<Map>();
if (TryInlineBuiltinMethodCall(expr, known_function, map,
expr->arguments()->length())) {
if (FLAG_trace_inlining) {
@ -9181,10 +9165,10 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) {
}
return;
}
if (TryInlineApiMethodCall(expr, receiver, types)) return;
if (TryInlineApiMethodCall(expr, receiver, maps)) return;
// Wrap the receiver if necessary.
if (NeedsWrappingFor(ToType(types->first()), known_function)) {
if (NeedsWrapping(maps->first(), known_function)) {
// Since HWrapReceiver currently cannot actually wrap numbers and
// strings, use the regular CallFunctionStub for method calls to wrap
// the receiver.

View File

@ -2282,8 +2282,6 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT
Type* ToType(Handle<Map> map);
private:
// Helpers for flow graph construction.
enum GlobalPropertyAccess {
@ -2434,16 +2432,15 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
class PropertyAccessInfo {
public:
PropertyAccessInfo(HOptimizedGraphBuilder* builder,
PropertyAccessType access_type,
Type* type,
PropertyAccessType access_type, Handle<Map> map,
Handle<String> name)
: lookup_(builder->isolate()),
builder_(builder),
access_type_(access_type),
type_(type),
map_(map),
name_(name),
field_type_(HType::Tagged()),
access_(HObjectAccess::ForMap()) { }
access_(HObjectAccess::ForMap()) {}
// Checkes whether this PropertyAccessInfo can be handled as a monomorphic
// load named. It additionally fills in the fields necessary to generate the
@ -2458,22 +2455,23 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
// PropertyAccessInfo is built for types->first().
bool CanAccessAsMonomorphic(SmallMapList* types);
bool NeedsWrappingFor(Handle<JSFunction> target) const;
Handle<Map> map();
Type* type() const { return type_; }
Handle<String> name() const { return name_; }
bool IsJSObjectFieldAccessor() {
int offset; // unused
return Accessors::IsJSObjectFieldAccessor<Type>(type_, name_, &offset);
return Accessors::IsJSObjectFieldAccessor(map(), name_, &offset);
}
bool GetJSObjectFieldAccess(HObjectAccess* access) {
int offset;
if (Accessors::IsJSObjectFieldAccessor<Type>(type_, name_, &offset)) {
if (type_->Is(Type::String())) {
if (Accessors::IsJSObjectFieldAccessor(map(), name_, &offset)) {
if (IsStringType()) {
DCHECK(String::Equals(isolate()->factory()->length_string(), name_));
*access = HObjectAccess::ForStringLength();
} else if (type_->Is(Type::Array())) {
} else if (IsArrayType()) {
DCHECK(String::Equals(isolate()->factory()->length_string(), name_));
*access = HObjectAccess::ForArrayLength(map()->elements_kind());
} else {
@ -2506,6 +2504,11 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
bool IsConfigurable() const { return lookup_.IsConfigurable(); }
bool IsReadOnly() const { return lookup_.IsReadOnly(); }
bool IsStringType() { return map_->instance_type() < FIRST_NONSTRING_TYPE; }
bool IsNumberType() { return map_->instance_type() == HEAP_NUMBER_TYPE; }
bool IsValueWrapped() { return IsStringType() || IsNumberType(); }
bool IsArrayType() { return map_->instance_type() == JS_ARRAY_TYPE; }
private:
Handle<Object> GetAccessorsFromMap(Handle<Map> map) const {
return handle(lookup_.GetValueFromMap(*map), isolate());
@ -2524,7 +2527,6 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
}
Representation representation() const { return lookup_.representation(); }
Type* ToType(Handle<Map> map) { return builder_->ToType(map); }
Zone* zone() { return builder_->zone(); }
CompilationInfo* top_info() { return builder_->top_info(); }
CompilationInfo* current_info() { return builder_->current_info(); }
@ -2543,7 +2545,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
LookupResult lookup_;
HOptimizedGraphBuilder* builder_;
PropertyAccessType access_type_;
Type* type_;
Handle<Map> map_;
Handle<String> name_;
Handle<JSObject> holder_;
Handle<JSFunction> accessor_;

View File

@ -17,9 +17,8 @@ namespace internal {
void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
MacroAssembler* masm, Handle<HeapType> type, Register receiver,
Register holder, int accessor_index, int expected_arguments,
Register scratch) {
MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
int accessor_index, int expected_arguments, Register scratch) {
// ----------- S t a t e -------------
// -- r0 : receiver
// -- r2 : name
@ -32,7 +31,7 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
DCHECK(!holder.is(scratch));
DCHECK(!receiver.is(scratch));
// Call the JavaScript getter with the receiver on the stack.
if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
if (map->IsJSGlobalObjectMap()) {
// Swap in the global receiver.
__ ldr(scratch,
FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
@ -57,9 +56,8 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
MacroAssembler* masm, Handle<HeapType> type, Register receiver,
Register holder, int accessor_index, int expected_arguments,
Register scratch) {
MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
int accessor_index, int expected_arguments, Register scratch) {
// ----------- S t a t e -------------
// -- lr : return address
// -----------------------------------
@ -74,7 +72,7 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
DCHECK(!receiver.is(scratch));
DCHECK(!value().is(scratch));
// Call the JavaScript setter with receiver and value on the stack.
if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
if (map->IsJSGlobalObjectMap()) {
// Swap in the global receiver.
__ ldr(scratch,
FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
@ -415,7 +413,7 @@ Register PropertyHandlerCompiler::CheckPrototypes(
Register object_reg, Register holder_reg, Register scratch1,
Register scratch2, Handle<Name> name, Label* miss,
PrototypeCheckType check) {
Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate()));
Handle<Map> receiver_map = map();
// Make sure there's no overlap between holder and object registers.
DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
@ -427,8 +425,8 @@ Register PropertyHandlerCompiler::CheckPrototypes(
int depth = 0;
Handle<JSObject> current = Handle<JSObject>::null();
if (type()->IsConstant()) {
current = Handle<JSObject>::cast(type()->AsConstant()->Value());
if (receiver_map->IsJSGlobalObjectMap()) {
current = isolate()->global_object();
}
Handle<JSObject> prototype = Handle<JSObject>::null();
Handle<Map> current_map = receiver_map;

View File

@ -32,7 +32,7 @@ void PropertyICCompiler::GenerateRuntimeSetProperty(
#define __ ACCESS_MASM(masm())
Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types,
Handle<Code> PropertyICCompiler::CompilePolymorphic(MapHandleList* maps,
CodeHandleList* handlers,
Handle<Name> name,
Code::StubType type,
@ -59,7 +59,7 @@ Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types,
}
Label number_case;
Label* smi_target = IncludesNumberType(types) ? &number_case : &miss;
Label* smi_target = IncludesNumberMap(maps) ? &number_case : &miss;
__ JumpIfSmi(receiver(), smi_target);
// Polymorphic keyed stores may use the map register
@ -67,17 +67,16 @@ Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types,
DCHECK(kind() != Code::KEYED_STORE_IC ||
map_reg.is(ElementTransitionAndStoreDescriptor::MapRegister()));
int receiver_count = types->length();
int receiver_count = maps->length();
int number_of_handled_maps = 0;
__ ldr(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset));
for (int current = 0; current < receiver_count; ++current) {
Handle<HeapType> type = types->at(current);
Handle<Map> map = IC::TypeToMap(*type, isolate());
Handle<Map> map = maps->at(current);
if (!map->is_deprecated()) {
number_of_handled_maps++;
Handle<WeakCell> cell = Map::WeakCellForMap(map);
__ CmpWeakValue(map_reg, cell, scratch2());
if (type->Is(HeapType::Number())) {
if (map->instance_type() == HEAP_NUMBER_TYPE) {
DCHECK(!number_case.is_unused());
__ bind(&number_case);
}

View File

@ -223,9 +223,8 @@ void PropertyHandlerCompiler::GenerateApiAccessorCall(
void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
MacroAssembler* masm, Handle<HeapType> type, Register receiver,
Register holder, int accessor_index, int expected_arguments,
Register scratch) {
MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
int accessor_index, int expected_arguments, Register scratch) {
// ----------- S t a t e -------------
// -- lr : return address
// -----------------------------------
@ -241,7 +240,7 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
DCHECK(!AreAliased(receiver, scratch));
DCHECK(!AreAliased(value(), scratch));
// Call the JavaScript setter with receiver and value on the stack.
if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
if (map->IsJSGlobalObjectMap()) {
// Swap in the global receiver.
__ Ldr(scratch,
FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
@ -269,9 +268,8 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
MacroAssembler* masm, Handle<HeapType> type, Register receiver,
Register holder, int accessor_index, int expected_arguments,
Register scratch) {
MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
int accessor_index, int expected_arguments, Register scratch) {
{
FrameScope scope(masm, StackFrame::INTERNAL);
@ -279,7 +277,7 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
DCHECK(!AreAliased(holder, scratch));
DCHECK(!AreAliased(receiver, scratch));
// Call the JavaScript getter with the receiver on the stack.
if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
if (map->IsJSGlobalObjectMap()) {
// Swap in the global receiver.
__ Ldr(scratch,
FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
@ -465,7 +463,7 @@ Register PropertyHandlerCompiler::CheckPrototypes(
Register object_reg, Register holder_reg, Register scratch1,
Register scratch2, Handle<Name> name, Label* miss,
PrototypeCheckType check) {
Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate()));
Handle<Map> receiver_map = map();
// object_reg and holder_reg registers can alias.
DCHECK(!AreAliased(object_reg, scratch1, scratch2));
@ -476,8 +474,8 @@ Register PropertyHandlerCompiler::CheckPrototypes(
int depth = 0;
Handle<JSObject> current = Handle<JSObject>::null();
if (type()->IsConstant()) {
current = Handle<JSObject>::cast(type()->AsConstant()->Value());
if (receiver_map->IsJSGlobalObjectMap()) {
current = isolate()->global_object();
}
Handle<JSObject> prototype = Handle<JSObject>::null();
Handle<Map> current_map = receiver_map;

View File

@ -33,7 +33,7 @@ void PropertyICCompiler::GenerateRuntimeSetProperty(
#define __ ACCESS_MASM(masm())
Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types,
Handle<Code> PropertyICCompiler::CompilePolymorphic(MapHandleList* maps,
CodeHandleList* handlers,
Handle<Name> name,
Code::StubType type,
@ -59,7 +59,7 @@ Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types,
}
Label number_case;
Label* smi_target = IncludesNumberType(types) ? &number_case : &miss;
Label* smi_target = IncludesNumberMap(maps) ? &number_case : &miss;
__ JumpIfSmi(receiver(), smi_target);
// Polymorphic keyed stores may use the map register
@ -67,18 +67,17 @@ Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types,
DCHECK(kind() != Code::KEYED_STORE_IC ||
map_reg.is(ElementTransitionAndStoreDescriptor::MapRegister()));
__ Ldr(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset));
int receiver_count = types->length();
int receiver_count = maps->length();
int number_of_handled_maps = 0;
for (int current = 0; current < receiver_count; ++current) {
Handle<HeapType> type = types->at(current);
Handle<Map> map = IC::TypeToMap(*type, isolate());
Handle<Map> map = maps->at(current);
if (!map->is_deprecated()) {
number_of_handled_maps++;
Handle<WeakCell> cell = Map::WeakCellForMap(map);
__ CmpWeakValue(map_reg, cell, scratch2());
Label try_next;
__ B(ne, &try_next);
if (type->Is(HeapType::Number())) {
if (map->instance_type() == HEAP_NUMBER_TYPE) {
DCHECK(!number_case.is_unused());
__ Bind(&number_case);
}

View File

@ -51,12 +51,12 @@ bool CallOptimization::IsCompatibleReceiver(Handle<Object> receiver,
DCHECK(is_simple_api_call());
if (!receiver->IsHeapObject()) return false;
Handle<Map> map(HeapObject::cast(*receiver)->map());
return IsCompatibleReceiverType(map, holder);
return IsCompatibleReceiverMap(map, holder);
}
bool CallOptimization::IsCompatibleReceiverType(Handle<Map> map,
Handle<JSObject> holder) const {
bool CallOptimization::IsCompatibleReceiverMap(Handle<Map> map,
Handle<JSObject> holder) const {
HolderLookup holder_lookup;
Handle<JSObject> api_holder = LookupHolderOfExpectedType(map, &holder_lookup);
switch (holder_lookup) {

View File

@ -46,8 +46,8 @@ class CallOptimization BASE_EMBEDDED {
Handle<JSObject> holder) const;
// Check if the api holder is between the receiver and the holder.
bool IsCompatibleReceiverType(Handle<Map> receiver_map,
Handle<JSObject> holder) const;
bool IsCompatibleReceiverMap(Handle<Map> receiver_map,
Handle<JSObject> holder) const;
private:
void Initialize(Handle<JSFunction> function);

View File

@ -26,9 +26,8 @@ Handle<Code> PropertyHandlerCompiler::Find(Handle<Name> name,
Handle<Code> NamedLoadHandlerCompiler::ComputeLoadNonexistent(
Handle<Name> name, Handle<HeapType> type) {
Handle<Name> name, Handle<Map> receiver_map) {
Isolate* isolate = name->GetIsolate();
Handle<Map> receiver_map = IC::TypeToMap(*type, isolate);
if (receiver_map->prototype()->IsNull()) {
// TODO(jkummerow/verwaest): If there is no prototype and the property
// is nonexistent, introduce a builtin to handle this (fast properties
@ -37,7 +36,7 @@ Handle<Code> NamedLoadHandlerCompiler::ComputeLoadNonexistent(
}
CacheHolderFlag flag;
Handle<Map> stub_holder_map =
IC::GetHandlerCacheHolder(*type, false, isolate, &flag);
IC::GetHandlerCacheHolder(receiver_map, false, isolate, &flag);
// If no dictionary mode objects are present in the prototype chain, the load
// nonexistent IC stub can be shared for all names for a given map and we use
@ -62,7 +61,7 @@ Handle<Code> NamedLoadHandlerCompiler::ComputeLoadNonexistent(
cache_name, stub_holder_map, Code::LOAD_IC, flag, Code::FAST);
if (!handler.is_null()) return handler;
NamedLoadHandlerCompiler compiler(isolate, type, last, flag);
NamedLoadHandlerCompiler compiler(isolate, receiver_map, last, flag);
handler = compiler.CompileLoadNonexistent(cache_name);
Map::UpdateCodeCache(stub_holder_map, cache_name, handler);
return handler;
@ -82,11 +81,6 @@ Handle<Code> PropertyHandlerCompiler::GetCode(Code::Kind kind,
}
void PropertyHandlerCompiler::set_type_for_object(Handle<Object> object) {
type_ = IC::CurrentTypeOf(object, isolate());
}
#define __ ACCESS_MASM(masm())
@ -95,13 +89,13 @@ Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg,
Label* miss) {
PrototypeCheckType check_type = CHECK_ALL_MAPS;
int function_index = -1;
if (type()->Is(HeapType::String())) {
if (map()->instance_type() < FIRST_NONSTRING_TYPE) {
function_index = Context::STRING_FUNCTION_INDEX;
} else if (type()->Is(HeapType::Symbol())) {
} else if (map()->instance_type() == SYMBOL_TYPE) {
function_index = Context::SYMBOL_FUNCTION_INDEX;
} else if (type()->Is(HeapType::Number())) {
} else if (map()->instance_type() == HEAP_NUMBER_TYPE) {
function_index = Context::NUMBER_FUNCTION_INDEX;
} else if (type()->Is(HeapType::Boolean())) {
} else if (*map() == isolate()->heap()->boolean_map()) {
function_index = Context::BOOLEAN_FUNCTION_INDEX;
} else {
check_type = SKIP_RECEIVER;
@ -112,7 +106,8 @@ Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg,
scratch1(), miss);
Object* function = isolate()->native_context()->get(function_index);
Object* prototype = JSFunction::cast(function)->instance_prototype();
set_type_for_object(handle(prototype, isolate()));
Handle<Map> map(JSObject::cast(prototype)->map());
set_map(map);
object_reg = scratch1();
}
@ -155,7 +150,7 @@ void PropertyHandlerCompiler::NonexistentFrontendHeader(Handle<Name> name,
Handle<Map> last_map;
if (holder().is_null()) {
holder_reg = receiver();
last_map = IC::TypeToMap(*type(), isolate());
last_map = map();
// If |type| has null as its prototype, |holder()| is
// Handle<JSObject>::null().
DCHECK(last_map->prototype() == isolate()->heap()->null_value());
@ -168,7 +163,7 @@ void PropertyHandlerCompiler::NonexistentFrontendHeader(Handle<Name> name,
if (last_map->IsJSGlobalObjectMap()) {
Handle<JSGlobalObject> global =
holder().is_null()
? Handle<JSGlobalObject>::cast(type()->AsConstant()->Value())
? Handle<JSGlobalObject>::cast(isolate()->global_object())
: Handle<JSGlobalObject>::cast(holder());
GenerateCheckPropertyCell(masm(), global, name, scratch1, miss);
} else {
@ -236,8 +231,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback(
int accessor_index) {
DCHECK(call_optimization.is_simple_api_call());
Register holder = Frontend(name);
Handle<Map> receiver_map = IC::TypeToMap(*type(), isolate());
GenerateApiAccessorCall(masm(), call_optimization, receiver_map, receiver(),
GenerateApiAccessorCall(masm(), call_optimization, map(), receiver(),
scratch2(), false, no_reg, holder, accessor_index);
return GetCode(kind(), Code::FAST, name);
}
@ -296,8 +290,8 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadInterceptor(
Handle<ExecutableAccessorInfo> info =
Handle<ExecutableAccessorInfo>::cast(accessors);
inline_followup = info->getter() != NULL &&
ExecutableAccessorInfo::IsCompatibleReceiverType(
isolate(), info, type());
ExecutableAccessorInfo::IsCompatibleReceiverMap(
isolate(), info, map());
} else if (accessors->IsAccessorPair()) {
Handle<JSObject> property_holder(it->GetHolder<JSObject>());
Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(),
@ -306,9 +300,9 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadInterceptor(
if (!property_holder->HasFastProperties()) break;
auto function = Handle<JSFunction>::cast(getter);
CallOptimization call_optimization(function);
Handle<Map> receiver_map = IC::TypeToMap(*type(), isolate());
Handle<Map> receiver_map = map();
inline_followup = call_optimization.is_simple_api_call() &&
call_optimization.IsCompatibleReceiverType(
call_optimization.IsCompatibleReceiverMap(
receiver_map, property_holder);
}
}
@ -335,7 +329,8 @@ void NamedLoadHandlerCompiler::GenerateLoadPostInterceptor(
LookupIterator* it, Register interceptor_reg) {
Handle<JSObject> real_named_property_holder(it->GetHolder<JSObject>());
set_type_for_object(holder());
Handle<Map> holder_map(holder()->map());
set_map(holder_map);
set_holder(real_named_property_holder);
Label miss;
@ -369,8 +364,7 @@ void NamedLoadHandlerCompiler::GenerateLoadPostInterceptor(
auto function = handle(JSFunction::cast(
AccessorPair::cast(*it->GetAccessors())->getter()));
CallOptimization call_optimization(function);
Handle<Map> receiver_map = IC::TypeToMap(*type(), isolate());
GenerateApiAccessorCall(masm(), call_optimization, receiver_map,
GenerateApiAccessorCall(masm(), call_optimization, holder_map,
receiver(), scratch2(), false, no_reg, reg,
it->GetAccessorIndex());
}
@ -381,7 +375,7 @@ void NamedLoadHandlerCompiler::GenerateLoadPostInterceptor(
Handle<Code> NamedLoadHandlerCompiler::CompileLoadViaGetter(
Handle<Name> name, int accessor_index, int expected_arguments) {
Register holder = Frontend(name);
GenerateLoadViaGetter(masm(), type(), receiver(), holder, accessor_index,
GenerateLoadViaGetter(masm(), map(), receiver(), holder, accessor_index,
expected_arguments, scratch2());
return GetCode(kind(), Code::FAST, name);
}
@ -471,7 +465,7 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter(
Handle<JSObject> object, Handle<Name> name, int accessor_index,
int expected_arguments) {
Register holder = Frontend(name);
GenerateStoreViaSetter(masm(), type(), receiver(), holder, accessor_index,
GenerateStoreViaSetter(masm(), map(), receiver(), holder, accessor_index,
expected_arguments, scratch2());
return GetCode(kind(), Code::FAST, name);

View File

@ -21,11 +21,10 @@ class PropertyHandlerCompiler : public PropertyAccessCompiler {
CacheHolderFlag cache_holder, Code::StubType type);
protected:
PropertyHandlerCompiler(Isolate* isolate, Code::Kind kind,
Handle<HeapType> type, Handle<JSObject> holder,
CacheHolderFlag cache_holder)
PropertyHandlerCompiler(Isolate* isolate, Code::Kind kind, Handle<Map> map,
Handle<JSObject> holder, CacheHolderFlag cache_holder)
: PropertyAccessCompiler(isolate, kind, cache_holder),
type_(type),
map_(map),
holder_(holder) {}
virtual ~PropertyHandlerCompiler() {}
@ -99,23 +98,23 @@ class PropertyHandlerCompiler : public PropertyAccessCompiler {
PrototypeCheckType check = CHECK_ALL_MAPS);
Handle<Code> GetCode(Code::Kind kind, Code::StubType type, Handle<Name> name);
void set_type_for_object(Handle<Object> object);
void set_holder(Handle<JSObject> holder) { holder_ = holder; }
Handle<HeapType> type() const { return type_; }
Handle<Map> map() const { return map_; }
void set_map(Handle<Map> map) { map_ = map; }
Handle<JSObject> holder() const { return holder_; }
private:
Handle<HeapType> type_;
Handle<Map> map_;
Handle<JSObject> holder_;
};
class NamedLoadHandlerCompiler : public PropertyHandlerCompiler {
public:
NamedLoadHandlerCompiler(Isolate* isolate, Handle<HeapType> type,
NamedLoadHandlerCompiler(Isolate* isolate, Handle<Map> map,
Handle<JSObject> holder,
CacheHolderFlag cache_holder)
: PropertyHandlerCompiler(isolate, Code::LOAD_IC, type, holder,
: PropertyHandlerCompiler(isolate, Code::LOAD_IC, map, holder,
cache_holder) {}
virtual ~NamedLoadHandlerCompiler() {}
@ -144,16 +143,16 @@ class NamedLoadHandlerCompiler : public PropertyHandlerCompiler {
// Static interface
static Handle<Code> ComputeLoadNonexistent(Handle<Name> name,
Handle<HeapType> type);
Handle<Map> map);
static void GenerateLoadViaGetter(MacroAssembler* masm, Handle<HeapType> type,
static void GenerateLoadViaGetter(MacroAssembler* masm, Handle<Map> map,
Register receiver, Register holder,
int accessor_index, int expected_arguments,
Register scratch);
static void GenerateLoadViaGetterForDeopt(MacroAssembler* masm) {
GenerateLoadViaGetter(masm, Handle<HeapType>::null(), no_reg, no_reg, -1,
-1, no_reg);
GenerateLoadViaGetter(masm, Handle<Map>::null(), no_reg, no_reg, -1, -1,
no_reg);
}
static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
@ -213,9 +212,9 @@ class NamedLoadHandlerCompiler : public PropertyHandlerCompiler {
class NamedStoreHandlerCompiler : public PropertyHandlerCompiler {
public:
explicit NamedStoreHandlerCompiler(Isolate* isolate, Handle<HeapType> type,
explicit NamedStoreHandlerCompiler(Isolate* isolate, Handle<Map> map,
Handle<JSObject> holder)
: PropertyHandlerCompiler(isolate, Code::STORE_IC, type, holder,
: PropertyHandlerCompiler(isolate, Code::STORE_IC, map, holder,
kCacheOnReceiver) {}
virtual ~NamedStoreHandlerCompiler() {}
@ -233,14 +232,14 @@ class NamedStoreHandlerCompiler : public PropertyHandlerCompiler {
int expected_arguments);
Handle<Code> CompileStoreInterceptor(Handle<Name> name);
static void GenerateStoreViaSetter(MacroAssembler* masm,
Handle<HeapType> type, Register receiver,
Register holder, int accessor_index,
int expected_arguments, Register scratch);
static void GenerateStoreViaSetter(MacroAssembler* masm, Handle<Map> map,
Register receiver, Register holder,
int accessor_index, int expected_arguments,
Register scratch);
static void GenerateStoreViaSetterForDeopt(MacroAssembler* masm) {
GenerateStoreViaSetter(masm, Handle<HeapType>::null(), no_reg, no_reg, -1,
-1, no_reg);
GenerateStoreViaSetter(masm, Handle<Map>::null(), no_reg, no_reg, -1, -1,
no_reg);
}
static void GenerateSlow(MacroAssembler* masm);
@ -284,8 +283,8 @@ class ElementHandlerCompiler : public PropertyHandlerCompiler {
public:
explicit ElementHandlerCompiler(Isolate* isolate)
: PropertyHandlerCompiler(isolate, Code::KEYED_LOAD_IC,
Handle<HeapType>::null(),
Handle<JSObject>::null(), kCacheOnReceiver) {}
Handle<Map>::null(), Handle<JSObject>::null(),
kCacheOnReceiver) {}
virtual ~ElementHandlerCompiler() {}

View File

@ -17,9 +17,8 @@ namespace internal {
void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
MacroAssembler* masm, Handle<HeapType> type, Register receiver,
Register holder, int accessor_index, int expected_arguments,
Register scratch) {
MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
int accessor_index, int expected_arguments, Register scratch) {
{
FrameScope scope(masm, StackFrame::INTERNAL);
@ -27,7 +26,7 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
DCHECK(!holder.is(scratch));
DCHECK(!receiver.is(scratch));
// Call the JavaScript getter with the receiver on the stack.
if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
if (map->IsJSGlobalObjectMap()) {
// Swap in the global receiver.
__ mov(scratch,
FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
@ -237,9 +236,8 @@ void PropertyHandlerCompiler::GenerateCheckPropertyCell(
void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
MacroAssembler* masm, Handle<HeapType> type, Register receiver,
Register holder, int accessor_index, int expected_arguments,
Register scratch) {
MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
int accessor_index, int expected_arguments, Register scratch) {
// ----------- S t a t e -------------
// -- esp[0] : return address
// -----------------------------------
@ -254,7 +252,7 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
DCHECK(!receiver.is(scratch));
DCHECK(!value().is(scratch));
// Call the JavaScript setter with receiver and value on the stack.
if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
if (map->IsJSGlobalObjectMap()) {
__ mov(scratch,
FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
receiver = scratch;
@ -418,7 +416,7 @@ Register PropertyHandlerCompiler::CheckPrototypes(
Register object_reg, Register holder_reg, Register scratch1,
Register scratch2, Handle<Name> name, Label* miss,
PrototypeCheckType check) {
Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate()));
Handle<Map> receiver_map = map();
// Make sure there's no overlap between holder and object registers.
DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
@ -430,8 +428,9 @@ Register PropertyHandlerCompiler::CheckPrototypes(
int depth = 0;
Handle<JSObject> current = Handle<JSObject>::null();
if (type()->IsConstant())
current = Handle<JSObject>::cast(type()->AsConstant()->Value());
if (receiver_map->IsJSGlobalObjectMap()) {
current = isolate()->global_object();
}
Handle<JSObject> prototype = Handle<JSObject>::null();
Handle<Map> current_map = receiver_map;
Handle<Map> holder_map(holder()->map());

View File

@ -36,7 +36,7 @@ void PropertyICCompiler::GenerateRuntimeSetProperty(
#undef __
#define __ ACCESS_MASM(masm())
Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types,
Handle<Code> PropertyICCompiler::CompilePolymorphic(MapHandleList* maps,
CodeHandleList* handlers,
Handle<Name> name,
Code::StubType type,
@ -63,7 +63,7 @@ Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types,
}
Label number_case;
Label* smi_target = IncludesNumberType(types) ? &number_case : &miss;
Label* smi_target = IncludesNumberMap(maps) ? &number_case : &miss;
__ JumpIfSmi(receiver(), smi_target);
// Polymorphic keyed stores may use the map register
@ -71,16 +71,15 @@ Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types,
DCHECK(kind() != Code::KEYED_STORE_IC ||
map_reg.is(ElementTransitionAndStoreDescriptor::MapRegister()));
__ mov(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset));
int receiver_count = types->length();
int receiver_count = maps->length();
int number_of_handled_maps = 0;
for (int current = 0; current < receiver_count; ++current) {
Handle<HeapType> type = types->at(current);
Handle<Map> map = IC::TypeToMap(*type, isolate());
Handle<Map> map = maps->at(current);
if (!map->is_deprecated()) {
number_of_handled_maps++;
Handle<WeakCell> cell = Map::WeakCellForMap(map);
__ CmpWeakValue(map_reg, cell, scratch2());
if (type->Is(HeapType::Number())) {
if (map->instance_type() == HEAP_NUMBER_TYPE) {
DCHECK(!number_case.is_unused());
__ bind(&number_case);
}

View File

@ -25,30 +25,30 @@ Handle<Code> PropertyICCompiler::Find(Handle<Name> name,
}
bool PropertyICCompiler::IncludesNumberType(TypeHandleList* types) {
for (int i = 0; i < types->length(); ++i) {
if (types->at(i)->Is(HeapType::Number())) return true;
bool PropertyICCompiler::IncludesNumberMap(MapHandleList* maps) {
for (int i = 0; i < maps->length(); ++i) {
if (maps->at(i)->instance_type() == HEAP_NUMBER_TYPE) return true;
}
return false;
}
Handle<Code> PropertyICCompiler::CompileMonomorphic(Handle<HeapType> type,
Handle<Code> PropertyICCompiler::CompileMonomorphic(Handle<Map> map,
Handle<Code> handler,
Handle<Name> name,
IcCheckType check) {
TypeHandleList types(1);
MapHandleList maps(1);
CodeHandleList handlers(1);
types.Add(type);
maps.Add(map);
handlers.Add(handler);
Code::StubType stub_type = handler->type();
return CompilePolymorphic(&types, &handlers, name, stub_type, check);
return CompilePolymorphic(&maps, &handlers, name, stub_type, check);
}
Handle<Code> PropertyICCompiler::ComputeMonomorphic(
Code::Kind kind, Handle<Name> name, Handle<HeapType> type,
Handle<Code> handler, ExtraICState extra_ic_state) {
Code::Kind kind, Handle<Name> name, Handle<Map> map, Handle<Code> handler,
ExtraICState extra_ic_state) {
Isolate* isolate = name->GetIsolate();
if (handler.is_identical_to(isolate->builtins()->LoadIC_Normal()) ||
handler.is_identical_to(isolate->builtins()->StoreIC_Normal())) {
@ -56,7 +56,7 @@ Handle<Code> PropertyICCompiler::ComputeMonomorphic(
}
CacheHolderFlag flag;
Handle<Map> stub_holder = IC::GetICCacheHolder(*type, isolate, &flag);
Handle<Map> stub_holder = IC::GetICCacheHolder(map, isolate, &flag);
if (kind == Code::KEYED_STORE_IC) {
// Always set the "property" bit.
extra_ic_state =
@ -72,14 +72,14 @@ Handle<Code> PropertyICCompiler::ComputeMonomorphic(
// There are multiple string maps that all use the same prototype. That
// prototype cannot hold multiple handlers, one for each of the string maps,
// for a single name. Hence, turn off caching of the IC.
bool can_be_cached = !type->Is(HeapType::String());
bool can_be_cached = map->instance_type() >= FIRST_NONSTRING_TYPE;
if (can_be_cached) {
ic = Find(name, stub_holder, kind, extra_ic_state, flag);
if (!ic.is_null()) return ic;
}
PropertyICCompiler ic_compiler(isolate, kind, extra_ic_state, flag);
ic = ic_compiler.CompileMonomorphic(type, handler, name, PROPERTY);
ic = ic_compiler.CompileMonomorphic(map, handler, name, PROPERTY);
if (can_be_cached) Map::UpdateCodeCache(stub_holder, name, ic);
return ic;
@ -98,9 +98,8 @@ Handle<Code> PropertyICCompiler::ComputeKeyedLoadMonomorphic(
Handle<Code> stub = ComputeKeyedLoadMonomorphicHandler(receiver_map);
PropertyICCompiler compiler(isolate, Code::KEYED_LOAD_IC);
Handle<Code> code =
compiler.CompileMonomorphic(HeapType::Class(receiver_map, isolate), stub,
isolate->factory()->empty_string(), ELEMENT);
Handle<Code> code = compiler.CompileMonomorphic(
receiver_map, stub, isolate->factory()->empty_string(), ELEMENT);
Map::UpdateCodeCache(receiver_map, name, code);
return code;
@ -256,7 +255,6 @@ Handle<Code> PropertyICCompiler::ComputeCompareNil(Handle<Map> receiver_map,
}
// TODO(verwaest): Change this method so it takes in a TypeHandleList.
Handle<Code> PropertyICCompiler::ComputeKeyedLoadPolymorphic(
MapHandleList* receiver_maps) {
Isolate* isolate = receiver_maps->at(0)->GetIsolate();
@ -267,17 +265,13 @@ Handle<Code> PropertyICCompiler::ComputeKeyedLoadPolymorphic(
Handle<Object> probe = cache->Lookup(receiver_maps, flags);
if (probe->IsCode()) return Handle<Code>::cast(probe);
TypeHandleList types(receiver_maps->length());
for (int i = 0; i < receiver_maps->length(); i++) {
types.Add(HeapType::Class(receiver_maps->at(i), isolate));
}
CodeHandleList handlers(receiver_maps->length());
ElementHandlerCompiler compiler(isolate);
compiler.CompileElementHandlers(receiver_maps, &handlers);
PropertyICCompiler ic_compiler(isolate, Code::KEYED_LOAD_IC);
Handle<Code> code = ic_compiler.CompilePolymorphic(
&types, &handlers, isolate->factory()->empty_string(), Code::NORMAL,
ELEMENT);
receiver_maps, &handlers, isolate->factory()->empty_string(),
Code::NORMAL, ELEMENT);
isolate->counters()->keyed_load_polymorphic_stubs()->Increment();
@ -287,13 +281,13 @@ Handle<Code> PropertyICCompiler::ComputeKeyedLoadPolymorphic(
Handle<Code> PropertyICCompiler::ComputePolymorphic(
Code::Kind kind, TypeHandleList* types, CodeHandleList* handlers,
int valid_types, Handle<Name> name, ExtraICState extra_ic_state) {
Code::Kind kind, MapHandleList* maps, CodeHandleList* handlers,
int valid_maps, Handle<Name> name, ExtraICState extra_ic_state) {
Handle<Code> handler = handlers->at(0);
Code::StubType type = valid_types == 1 ? handler->type() : Code::NORMAL;
Code::StubType type = valid_maps == 1 ? handler->type() : Code::NORMAL;
DCHECK(kind == Code::LOAD_IC || kind == Code::STORE_IC);
PropertyICCompiler ic_compiler(name->GetIsolate(), kind, extra_ic_state);
return ic_compiler.CompilePolymorphic(types, handlers, name, type, PROPERTY);
return ic_compiler.CompilePolymorphic(maps, handlers, name, type, PROPERTY);
}

View File

@ -24,10 +24,9 @@ class PropertyICCompiler : public PropertyAccessCompiler {
ExtraICState extra_state);
static Handle<Code> ComputeMonomorphic(Code::Kind kind, Handle<Name> name,
Handle<HeapType> type,
Handle<Code> handler,
Handle<Map> map, Handle<Code> handler,
ExtraICState extra_ic_state);
static Handle<Code> ComputePolymorphic(Code::Kind kind, TypeHandleList* types,
static Handle<Code> ComputePolymorphic(Code::Kind kind, MapHandleList* maps,
CodeHandleList* handlers,
int number_of_valid_maps,
Handle<Name> name,
@ -76,11 +75,11 @@ class PropertyICCompiler : public PropertyAccessCompiler {
Handle<Code> CompileStoreGeneric(Code::Flags flags);
Handle<Code> CompileStoreMegamorphic(Code::Flags flags);
Handle<Code> CompileMonomorphic(Handle<HeapType> type, Handle<Code> handler,
Handle<Code> CompileMonomorphic(Handle<Map> map, Handle<Code> handler,
Handle<Name> name, IcCheckType check);
Handle<Code> CompilePolymorphic(TypeHandleList* types,
CodeHandleList* handlers, Handle<Name> name,
Code::StubType type, IcCheckType check);
Handle<Code> CompilePolymorphic(MapHandleList* maps, CodeHandleList* handlers,
Handle<Name> name, Code::StubType type,
IcCheckType check);
Handle<Code> CompileKeyedStoreMonomorphic(Handle<Map> receiver_map,
KeyedAccessStoreMode store_mode);
@ -90,7 +89,7 @@ class PropertyICCompiler : public PropertyAccessCompiler {
CodeHandleList* handler_stubs,
MapHandleList* transitioned_maps);
bool IncludesNumberType(TypeHandleList* types);
bool IncludesNumberMap(MapHandleList* maps);
Handle<Code> GetCode(Code::Kind kind, Code::StubType type, Handle<Name> name,
InlineCacheState state = MONOMORPHIC);

View File

@ -161,15 +161,15 @@ Code* IC::raw_target() const {
void IC::UpdateTarget() { target_ = handle(raw_target(), isolate_); }
template <class TypeClass>
JSFunction* IC::GetRootConstructor(TypeClass* type, Context* native_context) {
if (type->Is(TypeClass::Boolean())) {
JSFunction* IC::GetRootConstructor(Map* receiver_map, Context* native_context) {
Isolate* isolate = receiver_map->GetIsolate();
if (receiver_map == isolate->heap()->boolean_map()) {
return native_context->boolean_function();
} else if (type->Is(TypeClass::Number())) {
} else if (receiver_map->instance_type() == HEAP_NUMBER_TYPE) {
return native_context->number_function();
} else if (type->Is(TypeClass::String())) {
} else if (receiver_map->instance_type() < FIRST_NONSTRING_TYPE) {
return native_context->string_function();
} else if (type->Is(TypeClass::Symbol())) {
} else if (receiver_map->instance_type() == SYMBOL_TYPE) {
return native_context->symbol_function();
} else {
return NULL;
@ -177,15 +177,15 @@ JSFunction* IC::GetRootConstructor(TypeClass* type, Context* native_context) {
}
Handle<Map> IC::GetHandlerCacheHolder(HeapType* type, bool receiver_is_holder,
Isolate* isolate, CacheHolderFlag* flag) {
Handle<Map> receiver_map = TypeToMap(type, isolate);
Handle<Map> IC::GetHandlerCacheHolder(Handle<Map> receiver_map,
bool receiver_is_holder, Isolate* isolate,
CacheHolderFlag* flag) {
if (receiver_is_holder) {
*flag = kCacheOnReceiver;
return receiver_map;
}
Context* native_context = *isolate->native_context();
JSFunction* builtin_ctor = GetRootConstructor(type, native_context);
JSFunction* builtin_ctor = GetRootConstructor(*receiver_map, native_context);
if (builtin_ctor != NULL) {
*flag = kCacheOnPrototypeReceiverIsPrimitive;
return handle(HeapObject::cast(builtin_ctor->instance_prototype())->map());
@ -198,16 +198,16 @@ Handle<Map> IC::GetHandlerCacheHolder(HeapType* type, bool receiver_is_holder,
}
Handle<Map> IC::GetICCacheHolder(HeapType* type, Isolate* isolate,
Handle<Map> IC::GetICCacheHolder(Handle<Map> map, Isolate* isolate,
CacheHolderFlag* flag) {
Context* native_context = *isolate->native_context();
JSFunction* builtin_ctor = GetRootConstructor(type, native_context);
JSFunction* builtin_ctor = GetRootConstructor(*map, native_context);
if (builtin_ctor != NULL) {
*flag = kCacheOnPrototype;
return handle(builtin_ctor->initial_map());
}
*flag = kCacheOnReceiver;
return TypeToMap(type, isolate);
return map;
}

View File

@ -265,11 +265,10 @@ static void LookupForRead(LookupIterator* it) {
bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
Handle<String> name) {
if (!IsNameCompatibleWithPrototypeFailure(name)) return false;
Handle<Map> receiver_map = TypeToMap(*receiver_type(), isolate());
if (UseVector()) {
maybe_handler_ = nexus()->FindHandlerForMap(receiver_map);
maybe_handler_ = nexus()->FindHandlerForMap(receiver_map());
} else {
maybe_handler_ = target()->FindHandlerForMap(*receiver_map);
maybe_handler_ = target()->FindHandlerForMap(*receiver_map());
}
// The current map wasn't handled yet. There's no reason to stay monomorphic,
@ -278,21 +277,20 @@ bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
// TODO(verwaest): Check if the current map is actually what the old map
// would transition to.
if (maybe_handler_.is_null()) {
if (!receiver_map->IsJSObjectMap()) return false;
if (!receiver_map()->IsJSObjectMap()) return false;
Map* first_map = FirstTargetMap();
if (first_map == NULL) return false;
Handle<Map> old_map(first_map);
if (old_map->is_deprecated()) return true;
if (IsMoreGeneralElementsKindTransition(old_map->elements_kind(),
receiver_map->elements_kind())) {
receiver_map()->elements_kind())) {
return true;
}
return false;
}
CacheHolderFlag flag;
Handle<Map> ic_holder_map(
GetICCacheHolder(*receiver_type(), isolate(), &flag));
Handle<Map> ic_holder_map(GetICCacheHolder(receiver_map(), isolate(), &flag));
DCHECK(flag != kCacheOnReceiver || receiver->IsJSObject());
DCHECK(flag != kCacheOnPrototype || !receiver->IsJSReceiver());
@ -332,7 +330,7 @@ bool IC::IsNameCompatibleWithPrototypeFailure(Handle<Object> name) {
void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) {
update_receiver_type(receiver);
update_receiver_map(receiver);
if (!name->IsString()) return;
if (state() != MONOMORPHIC && state() != POLYMORPHIC) return;
if (receiver->IsUndefined() || receiver->IsNull()) return;
@ -650,16 +648,16 @@ void IC::ConfigureVectorState(IC::State new_state) {
}
void IC::ConfigureVectorState(Handle<Name> name, Handle<HeapType> type,
void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
Handle<Code> handler) {
DCHECK(UseVector());
if (kind() == Code::LOAD_IC) {
LoadICNexus* nexus = casted_nexus<LoadICNexus>();
nexus->ConfigureMonomorphic(type, handler);
nexus->ConfigureMonomorphic(map, handler);
} else {
DCHECK(kind() == Code::KEYED_LOAD_IC);
KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>();
nexus->ConfigureMonomorphic(name, type, handler);
nexus->ConfigureMonomorphic(name, map, handler);
}
vector_set_ = true;
@ -668,16 +666,16 @@ void IC::ConfigureVectorState(Handle<Name> name, Handle<HeapType> type,
}
void IC::ConfigureVectorState(Handle<Name> name, TypeHandleList* types,
void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps,
CodeHandleList* handlers) {
DCHECK(UseVector());
if (kind() == Code::LOAD_IC) {
LoadICNexus* nexus = casted_nexus<LoadICNexus>();
nexus->ConfigurePolymorphic(types, handlers);
nexus->ConfigurePolymorphic(maps, handlers);
} else {
DCHECK(kind() == Code::KEYED_LOAD_IC);
KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>();
nexus->ConfigurePolymorphic(name, types, handlers);
nexus->ConfigurePolymorphic(name, maps, handlers);
}
vector_set_ = true;
@ -783,74 +781,70 @@ static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps,
bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Code> code) {
if (!code->is_handler()) return false;
if (target()->is_keyed_stub() && state() != PROTOTYPE_FAILURE) return false;
Handle<HeapType> type = receiver_type();
TypeHandleList types;
Handle<Map> map = receiver_map();
MapHandleList maps;
CodeHandleList handlers;
TargetTypes(&types);
int number_of_types = types.length();
int deprecated_types = 0;
TargetMaps(&maps);
int number_of_maps = maps.length();
int deprecated_maps = 0;
int handler_to_overwrite = -1;
for (int i = 0; i < number_of_types; i++) {
Handle<HeapType> current_type = types.at(i);
if (current_type->IsClass() &&
current_type->AsClass()->Map()->is_deprecated()) {
for (int i = 0; i < number_of_maps; i++) {
Handle<Map> current_map = maps.at(i);
if (current_map->is_deprecated()) {
// Filter out deprecated maps to ensure their instances get migrated.
++deprecated_types;
} else if (type->NowIs(current_type)) {
++deprecated_maps;
} else if (map.is_identical_to(current_map)) {
// If the receiver type is already in the polymorphic IC, this indicates
// there was a prototoype chain failure. In that case, just overwrite the
// handler.
handler_to_overwrite = i;
} else if (handler_to_overwrite == -1 && current_type->IsClass() &&
type->IsClass() &&
IsTransitionOfMonomorphicTarget(*current_type->AsClass()->Map(),
*type->AsClass()->Map())) {
} else if (handler_to_overwrite == -1 &&
IsTransitionOfMonomorphicTarget(*current_map, *map)) {
handler_to_overwrite = i;
}
}
int number_of_valid_types =
number_of_types - deprecated_types - (handler_to_overwrite != -1);
int number_of_valid_maps =
number_of_maps - deprecated_maps - (handler_to_overwrite != -1);
if (number_of_valid_types >= 4) return false;
if (number_of_types == 0 && state() != MONOMORPHIC &&
state() != POLYMORPHIC) {
if (number_of_valid_maps >= 4) return false;
if (number_of_maps == 0 && state() != MONOMORPHIC && state() != POLYMORPHIC) {
return false;
}
if (UseVector()) {
if (!nexus()->FindHandlers(&handlers, types.length())) return false;
if (!nexus()->FindHandlers(&handlers, maps.length())) return false;
} else {
if (!target()->FindHandlers(&handlers, types.length())) return false;
if (!target()->FindHandlers(&handlers, maps.length())) return false;
}
number_of_valid_types++;
if (number_of_valid_types > 1 && target()->is_keyed_stub()) return false;
number_of_valid_maps++;
if (number_of_valid_maps > 1 && target()->is_keyed_stub()) return false;
Handle<Code> ic;
if (number_of_valid_types == 1) {
if (number_of_valid_maps == 1) {
if (UseVector()) {
ConfigureVectorState(name, receiver_type(), code);
ConfigureVectorState(name, receiver_map(), code);
} else {
ic = PropertyICCompiler::ComputeMonomorphic(kind(), name, type, code,
ic = PropertyICCompiler::ComputeMonomorphic(kind(), name, map, code,
extra_ic_state());
}
} else {
if (handler_to_overwrite >= 0) {
handlers.Set(handler_to_overwrite, code);
if (!type->NowIs(types.at(handler_to_overwrite))) {
types.Set(handler_to_overwrite, type);
if (!map.is_identical_to(maps.at(handler_to_overwrite))) {
maps.Set(handler_to_overwrite, map);
}
} else {
types.Add(type);
maps.Add(map);
handlers.Add(code);
}
if (UseVector()) {
ConfigureVectorState(name, &types, &handlers);
ConfigureVectorState(name, &maps, &handlers);
} else {
ic = PropertyICCompiler::ComputePolymorphic(kind(), &types, &handlers,
number_of_valid_types, name,
ic = PropertyICCompiler::ComputePolymorphic(kind(), &maps, &handlers,
number_of_valid_maps, name,
extra_ic_state());
}
}
@ -860,66 +854,25 @@ bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Code> code) {
}
Handle<HeapType> IC::CurrentTypeOf(Handle<Object> object, Isolate* isolate) {
return object->IsJSGlobalObject()
? HeapType::Constant(Handle<JSGlobalObject>::cast(object), isolate)
: HeapType::NowOf(object, isolate);
}
Handle<Map> IC::TypeToMap(HeapType* type, Isolate* isolate) {
if (type->Is(HeapType::Number()))
return isolate->factory()->heap_number_map();
if (type->Is(HeapType::Boolean())) return isolate->factory()->boolean_map();
if (type->IsConstant()) {
return handle(
Handle<JSGlobalObject>::cast(type->AsConstant()->Value())->map());
}
DCHECK(type->IsClass());
return type->AsClass()->Map();
}
template <class T>
typename T::TypeHandle IC::MapToType(Handle<Map> map,
typename T::Region* region) {
if (map->instance_type() == HEAP_NUMBER_TYPE) {
return T::Number(region);
} else if (map->instance_type() == ODDBALL_TYPE) {
// The only oddballs that can be recorded in ICs are booleans.
return T::Boolean(region);
} else {
return T::Class(map, region);
}
}
template Type* IC::MapToType<Type>(Handle<Map> map, Zone* zone);
template Handle<HeapType> IC::MapToType<HeapType>(Handle<Map> map,
Isolate* region);
void IC::UpdateMonomorphicIC(Handle<Code> handler, Handle<Name> name) {
DCHECK(handler->is_handler());
if (UseVector()) {
ConfigureVectorState(name, receiver_type(), handler);
ConfigureVectorState(name, receiver_map(), handler);
} else {
Handle<Code> ic = PropertyICCompiler::ComputeMonomorphic(
kind(), name, receiver_type(), handler, extra_ic_state());
kind(), name, receiver_map(), handler, extra_ic_state());
set_target(*ic);
}
}
void IC::CopyICToMegamorphicCache(Handle<Name> name) {
TypeHandleList types;
MapHandleList maps;
CodeHandleList handlers;
TargetTypes(&types);
if (!target()->FindHandlers(&handlers, types.length())) return;
for (int i = 0; i < types.length(); i++) {
UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i));
TargetMaps(&maps);
if (!target()->FindHandlers(&handlers, maps.length())) return;
for (int i = 0; i < maps.length(); i++) {
UpdateMegamorphicCache(*maps.at(i), *name, *handlers.at(i));
}
}
@ -961,7 +914,7 @@ void IC::PatchCache(Handle<Name> name, Handle<Code> code) {
}
// Fall through.
case MEGAMORPHIC:
UpdateMegamorphicCache(*receiver_type(), *name, *code);
UpdateMegamorphicCache(*receiver_map(), *name, *code);
// Indicate that we've handled this case.
if (UseVector()) {
vector_set_ = true;
@ -1074,7 +1027,7 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) {
} else if (!lookup->IsFound()) {
if (kind() == Code::LOAD_IC) {
code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(lookup->name(),
receiver_type());
receiver_map());
// TODO(jkummerow/verwaest): Introduce a builtin that handles this case.
if (code.is_null()) code = slow_stub();
} else {
@ -1089,8 +1042,7 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) {
}
void IC::UpdateMegamorphicCache(HeapType* type, Name* name, Code* code) {
Map* map = *TypeToMap(type, isolate());
void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) {
isolate()->stub_cache()->Set(name, map, code);
}
@ -1100,7 +1052,7 @@ Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> value) {
lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>());
CacheHolderFlag flag;
Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder(
*receiver_type(), receiver_is_holder, isolate(), &flag);
receiver_map(), receiver_is_holder, isolate(), &flag);
Handle<Code> code = PropertyHandlerCompiler::Find(
lookup->name(), stub_holder_map, kind(), flag,
@ -1173,14 +1125,13 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
return function_prototype_stub.GetCode();
}
Handle<HeapType> type = receiver_type();
Handle<Map> map = receiver_map();
Handle<JSObject> holder = lookup->GetHolder<JSObject>();
bool receiver_is_holder = receiver.is_identical_to(holder);
switch (lookup->state()) {
case LookupIterator::INTERCEPTOR: {
DCHECK(!holder->GetNamedInterceptor()->getter()->IsUndefined());
NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
cache_holder);
NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
// Perform a lookup behind the interceptor. Copy the LookupIterator since
// the original iterator will be used to fetch the value.
LookupIterator it = *lookup;
@ -1195,8 +1146,8 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
DCHECK(receiver->IsJSObject());
Handle<JSObject> js_receiver = Handle<JSObject>::cast(receiver);
int object_offset;
if (Accessors::IsJSObjectFieldAccessor<HeapType>(type, lookup->name(),
&object_offset)) {
if (Accessors::IsJSObjectFieldAccessor(map, lookup->name(),
&object_offset)) {
FieldIndex index =
FieldIndex::ForInObjectOffset(object_offset, js_receiver->map());
return SimpleFieldLoad(index);
@ -1208,13 +1159,12 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
Handle<ExecutableAccessorInfo> info =
Handle<ExecutableAccessorInfo>::cast(accessors);
if (v8::ToCData<Address>(info->getter()) == 0) break;
if (!ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), info,
type)) {
if (!ExecutableAccessorInfo::IsCompatibleReceiverMap(isolate(), info,
map)) {
break;
}
if (!holder->HasFastProperties()) break;
NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
cache_holder);
NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
return compiler.CompileLoadCallback(lookup->name(), info);
}
if (accessors->IsAccessorPair()) {
@ -1230,8 +1180,7 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
break;
}
CallOptimization call_optimization(function);
NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
cache_holder);
NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
if (call_optimization.is_simple_api_call() &&
call_optimization.IsCompatibleReceiver(receiver, holder)) {
return compiler.CompileLoadCallback(lookup->name(), call_optimization,
@ -1249,15 +1198,15 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
if (lookup->is_dictionary_holder()) {
if (kind() != Code::LOAD_IC) break;
if (holder->IsGlobalObject()) {
NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
NamedLoadHandlerCompiler compiler(isolate(), map, holder,
cache_holder);
Handle<PropertyCell> cell = lookup->GetPropertyCell();
Handle<Code> code = compiler.CompileLoadGlobal(
cell, lookup->name(), lookup->IsConfigurable());
// TODO(verwaest): Move caching of these NORMAL stubs outside as well.
CacheHolderFlag flag;
Handle<Map> stub_holder_map = GetHandlerCacheHolder(
*type, receiver_is_holder, isolate(), &flag);
Handle<Map> stub_holder_map =
GetHandlerCacheHolder(map, receiver_is_holder, isolate(), &flag);
Map::UpdateCodeCache(stub_holder_map, lookup->name(), code);
return code;
}
@ -1275,8 +1224,7 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
if (receiver_is_holder) {
return SimpleFieldLoad(field);
}
NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
cache_holder);
NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
return compiler.CompileLoadField(lookup->name(), field);
}
@ -1286,8 +1234,7 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
LoadConstantStub stub(isolate(), lookup->GetConstantIndex());
return stub.GetCode();
}
NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
cache_holder);
NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
return compiler.CompileLoadConstant(lookup->name(),
lookup->GetConstantIndex());
}
@ -1334,7 +1281,7 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) {
if (FLAG_vector_ics) {
Handle<Code> handler =
PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(receiver_map);
ConfigureVectorState(Handle<Name>::null(), receiver_type(), handler);
ConfigureVectorState(Handle<Name>::null(), receiver_map, handler);
return null_handle;
}
return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map);
@ -1354,7 +1301,7 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) {
if (FLAG_vector_ics) {
Handle<Code> handler =
PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(receiver_map);
ConfigureVectorState(Handle<Name>::null(), receiver_type(), handler);
ConfigureVectorState(Handle<Name>::null(), receiver_map, handler);
return null_handle;
}
return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map);
@ -1382,11 +1329,8 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) {
CodeHandleList handlers(target_receiver_maps.length());
ElementHandlerCompiler compiler(isolate());
compiler.CompileElementHandlers(&target_receiver_maps, &handlers);
TypeHandleList types(target_receiver_maps.length());
for (int i = 0; i < target_receiver_maps.length(); i++) {
types.Add(HeapType::Class(target_receiver_maps.at(i), isolate()));
}
ConfigureVectorState(Handle<Name>::null(), &types, &handlers);
ConfigureVectorState(Handle<Name>::null(), &target_receiver_maps,
&handlers);
return null_handle;
}
@ -1492,7 +1436,7 @@ bool StoreIC::LookupForWrite(LookupIterator* it, Handle<Object> value,
it->PrepareForDataProperty(value);
// The previous receiver map might just have been deprecated,
// so reload it.
update_receiver_type(receiver);
update_receiver_map(receiver);
return true;
}
@ -1717,13 +1661,13 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
}
DCHECK(lookup->IsCacheableTransition());
NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
return compiler.CompileStoreTransition(transition, lookup->name());
}
case LookupIterator::INTERCEPTOR: {
DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined());
NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
return compiler.CompileStoreInterceptor(lookup->name());
}
@ -1740,12 +1684,12 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
TRACE_GENERIC_IC(isolate(), "StoreIC", "setter == 0");
break;
}
if (!ExecutableAccessorInfo::IsCompatibleReceiverType(
isolate(), info, receiver_type())) {
if (!ExecutableAccessorInfo::IsCompatibleReceiverMap(isolate(), info,
receiver_map())) {
TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver type");
break;
}
NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
return compiler.CompileStoreCallback(receiver, lookup->name(),
lookup->GetAccessorIndex());
} else if (accessors->IsAccessorPair()) {
@ -1757,7 +1701,7 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
}
Handle<JSFunction> function = Handle<JSFunction>::cast(setter);
CallOptimization call_optimization(function);
NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
if (call_optimization.is_simple_api_call() &&
call_optimization.IsCompatibleReceiver(receiver, holder)) {
return compiler.CompileStoreCallback(receiver, lookup->name(),
@ -1801,7 +1745,7 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
lookup->representation());
return stub.GetCode();
}
NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
return compiler.CompileStoreField(lookup);
}

View File

@ -92,14 +92,14 @@ class IC {
bool IsCallStub() const { return target()->is_call_stub(); }
#endif
template <class TypeClass>
static JSFunction* GetRootConstructor(TypeClass* type,
Context* native_context);
static inline Handle<Map> GetHandlerCacheHolder(HeapType* type,
static inline JSFunction* GetRootConstructor(Map* receiver_map,
Context* native_context);
static inline Handle<Map> GetHandlerCacheHolder(Handle<Map> receiver_map,
bool receiver_is_holder,
Isolate* isolate,
CacheHolderFlag* flag);
static inline Handle<Map> GetICCacheHolder(HeapType* type, Isolate* isolate,
static inline Handle<Map> GetICCacheHolder(Handle<Map> receiver_map,
Isolate* isolate,
CacheHolderFlag* flag);
static bool IsCleared(Code* code) {
@ -112,19 +112,6 @@ class IC {
return state == UNINITIALIZED || state == PREMONOMORPHIC;
}
// Utility functions to convert maps to types and back. There are two special
// cases:
// - The heap_number_map is used as a marker which includes heap numbers as
// well as smis.
// - The oddball map is only used for booleans.
static Handle<Map> TypeToMap(HeapType* type, Isolate* isolate);
template <class T>
static typename T::TypeHandle MapToType(Handle<Map> map,
typename T::Region* region);
static Handle<HeapType> CurrentTypeOf(Handle<Object> object,
Isolate* isolate);
static bool ICUseVector(Code::Kind kind) {
return (FLAG_vector_ics &&
(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC)) ||
@ -163,10 +150,10 @@ class IC {
// Configure for most states.
void ConfigureVectorState(IC::State new_state);
// Configure the vector for MONOMORPHIC.
void ConfigureVectorState(Handle<Name> name, Handle<HeapType> type,
void ConfigureVectorState(Handle<Name> name, Handle<Map> map,
Handle<Code> handler);
// Configure the vector for POLYMORPHIC.
void ConfigureVectorState(Handle<Name> name, TypeHandleList* types,
void ConfigureVectorState(Handle<Name> name, MapHandleList* maps,
CodeHandleList* handlers);
char TransitionMarkFromState(IC::State state);
@ -204,7 +191,7 @@ class IC {
void UpdateMonomorphicIC(Handle<Code> handler, Handle<Name> name);
bool UpdatePolymorphicIC(Handle<Name> name, Handle<Code> code);
void UpdateMegamorphicCache(HeapType* type, Name* name, Code* code);
void UpdateMegamorphicCache(Map* map, Name* name, Code* code);
void CopyICToMegamorphicCache(Handle<Name> name);
bool IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map);
@ -227,9 +214,13 @@ class IC {
ExtraICState extra_ic_state() const { return extra_ic_state_; }
void set_extra_ic_state(ExtraICState state) { extra_ic_state_ = state; }
Handle<HeapType> receiver_type() { return receiver_type_; }
void update_receiver_type(Handle<Object> receiver) {
receiver_type_ = CurrentTypeOf(receiver, isolate_);
Handle<Map> receiver_map() { return receiver_map_; }
void update_receiver_map(Handle<Object> receiver) {
if (receiver->IsSmi()) {
receiver_map_ = isolate_->factory()->heap_number_map();
} else {
receiver_map_ = handle(HeapObject::cast(*receiver)->map());
}
}
void TargetMaps(MapHandleList* list) {
@ -239,13 +230,6 @@ class IC {
}
}
void TargetTypes(TypeHandleList* list) {
FindTargetMaps();
for (int i = 0; i < target_maps_.length(); i++) {
list->Add(MapToType<HeapType>(target_maps_.at(i), isolate_));
}
}
Map* FirstTargetMap() {
FindTargetMaps();
return target_maps_.length() > 0 ? *target_maps_.at(0) : NULL;
@ -309,7 +293,7 @@ class IC {
State old_state_; // For saving if we marked as prototype failure.
State state_;
Code::Kind kind_;
Handle<HeapType> receiver_type_;
Handle<Map> receiver_map_;
MaybeHandle<Code> maybe_handler_;
ExtraICState extra_ic_state_;

View File

@ -215,9 +215,8 @@ void PropertyHandlerCompiler::GenerateCheckPropertyCell(
void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
MacroAssembler* masm, Handle<HeapType> type, Register receiver,
Register holder, int accessor_index, int expected_arguments,
Register scratch) {
MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
int accessor_index, int expected_arguments, Register scratch) {
// ----------- S t a t e -------------
// -- rsp[0] : return address
// -----------------------------------
@ -232,7 +231,7 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
DCHECK(!receiver.is(scratch));
DCHECK(!value().is(scratch));
// Call the JavaScript setter with receiver and value on the stack.
if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
if (map->IsJSGlobalObjectMap()) {
// Swap in the global receiver.
__ movp(scratch,
FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
@ -262,9 +261,8 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
MacroAssembler* masm, Handle<HeapType> type, Register receiver,
Register holder, int accessor_index, int expected_arguments,
Register scratch) {
MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder,
int accessor_index, int expected_arguments, Register scratch) {
// ----------- S t a t e -------------
// -- rax : receiver
// -- rcx : name
@ -277,7 +275,7 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
DCHECK(!holder.is(scratch));
DCHECK(!receiver.is(scratch));
// Call the JavaScript getter with the receiver on the stack.
if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
if (map->IsJSGlobalObjectMap()) {
// Swap in the global receiver.
__ movp(scratch,
FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
@ -416,7 +414,7 @@ Register PropertyHandlerCompiler::CheckPrototypes(
Register object_reg, Register holder_reg, Register scratch1,
Register scratch2, Handle<Name> name, Label* miss,
PrototypeCheckType check) {
Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate()));
Handle<Map> receiver_map = map();
// Make sure there's no overlap between holder and object registers.
DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
@ -430,8 +428,8 @@ Register PropertyHandlerCompiler::CheckPrototypes(
int depth = 0;
Handle<JSObject> current = Handle<JSObject>::null();
if (type()->IsConstant()) {
current = Handle<JSObject>::cast(type()->AsConstant()->Value());
if (receiver_map->IsJSGlobalObjectMap()) {
current = isolate()->global_object();
}
Handle<JSObject> prototype = Handle<JSObject>::null();
Handle<Map> current_map = receiver_map;

View File

@ -72,7 +72,7 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic(
}
Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types,
Handle<Code> PropertyICCompiler::CompilePolymorphic(MapHandleList* maps,
CodeHandleList* handlers,
Handle<Name> name,
Code::StubType type,
@ -99,7 +99,7 @@ Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types,
}
Label number_case;
Label* smi_target = IncludesNumberType(types) ? &number_case : &miss;
Label* smi_target = IncludesNumberMap(maps) ? &number_case : &miss;
__ JumpIfSmi(receiver(), smi_target);
// Polymorphic keyed stores may use the map register
@ -107,17 +107,16 @@ Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types,
DCHECK(kind() != Code::KEYED_STORE_IC ||
map_reg.is(ElementTransitionAndStoreDescriptor::MapRegister()));
__ movp(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset));
int receiver_count = types->length();
int receiver_count = maps->length();
int number_of_handled_maps = 0;
for (int current = 0; current < receiver_count; ++current) {
Handle<HeapType> type = types->at(current);
Handle<Map> map = IC::TypeToMap(*type, isolate());
Handle<Map> map = maps->at(current);
if (!map->is_deprecated()) {
number_of_handled_maps++;
Handle<WeakCell> cell = Map::WeakCellForMap(map);
// Check map and tail call if there's a match
__ CmpWeakValue(map_reg, cell, scratch2());
if (type->Is(HeapType::Number())) {
if (map->instance_type() == HEAP_NUMBER_TYPE) {
DCHECK(!number_case.is_unused());
__ bind(&number_case);
}

View File

@ -331,11 +331,10 @@ MaybeHandle<Object> Object::GetPropertyWithAccessor(Handle<Object> receiver,
}
bool AccessorInfo::IsCompatibleReceiverType(Isolate* isolate,
Handle<AccessorInfo> info,
Handle<HeapType> type) {
bool AccessorInfo::IsCompatibleReceiverMap(Isolate* isolate,
Handle<AccessorInfo> info,
Handle<Map> map) {
if (!info->HasExpectedReceiverType()) return true;
Handle<Map> map = IC::TypeToMap(*type, isolate);
if (!map->IsJSObjectMap()) return false;
return FunctionTemplateInfo::cast(info->expected_receiver_type())
->IsTemplateFor(*map);

View File

@ -10402,9 +10402,9 @@ class AccessorInfo: public Struct {
inline void set_property_attributes(PropertyAttributes attributes);
// Checks whether the given receiver is compatible with this accessor.
static bool IsCompatibleReceiverType(Isolate* isolate,
Handle<AccessorInfo> info,
Handle<HeapType> type);
static bool IsCompatibleReceiverMap(Isolate* isolate,
Handle<AccessorInfo> info,
Handle<Map> map);
inline bool IsCompatibleReceiver(Object* receiver);
DECLARE_CAST(AccessorInfo)

View File

@ -207,14 +207,13 @@ Handle<FixedArray> FeedbackNexus::EnsureArrayOfSize(int length) {
}
void FeedbackNexus::InstallHandlers(int start_index, TypeHandleList* types,
void FeedbackNexus::InstallHandlers(int start_index, MapHandleList* maps,
CodeHandleList* handlers) {
Isolate* isolate = GetIsolate();
Handle<FixedArray> array = handle(FixedArray::cast(GetFeedback()), isolate);
int receiver_count = types->length();
int receiver_count = maps->length();
for (int current = 0; current < receiver_count; ++current) {
Handle<HeapType> type = types->at(current);
Handle<Map> map = IC::TypeToMap(*type, isolate);
Handle<Map> map = maps->at(current);
Handle<WeakCell> cell = Map::WeakCellForMap(map);
array->set(start_index + (current * 2), *cell);
array->set(start_index + (current * 2 + 1), *handlers->at(current));
@ -333,10 +332,9 @@ void KeyedLoadICNexus::ConfigurePremonomorphic() {
}
void LoadICNexus::ConfigureMonomorphic(Handle<HeapType> type,
void LoadICNexus::ConfigureMonomorphic(Handle<Map> receiver_map,
Handle<Code> handler) {
Handle<FixedArray> array = EnsureArrayOfSize(2);
Handle<Map> receiver_map = IC::TypeToMap(*type, GetIsolate());
Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
array->set(0, *cell);
array->set(1, *handler);
@ -344,10 +342,9 @@ void LoadICNexus::ConfigureMonomorphic(Handle<HeapType> type,
void KeyedLoadICNexus::ConfigureMonomorphic(Handle<Name> name,
Handle<HeapType> type,
Handle<Map> receiver_map,
Handle<Code> handler) {
Handle<FixedArray> array = EnsureArrayOfSize(3);
Handle<Map> receiver_map = IC::TypeToMap(*type, GetIsolate());
if (name.is_null()) {
array->set(0, Smi::FromInt(0));
} else {
@ -359,25 +356,25 @@ void KeyedLoadICNexus::ConfigureMonomorphic(Handle<Name> name,
}
void LoadICNexus::ConfigurePolymorphic(TypeHandleList* types,
void LoadICNexus::ConfigurePolymorphic(MapHandleList* maps,
CodeHandleList* handlers) {
int receiver_count = types->length();
int receiver_count = maps->length();
EnsureArrayOfSize(receiver_count * 2);
InstallHandlers(0, types, handlers);
InstallHandlers(0, maps, handlers);
}
void KeyedLoadICNexus::ConfigurePolymorphic(Handle<Name> name,
TypeHandleList* types,
MapHandleList* maps,
CodeHandleList* handlers) {
int receiver_count = types->length();
int receiver_count = maps->length();
Handle<FixedArray> array = EnsureArrayOfSize(1 + receiver_count * 2);
if (name.is_null()) {
array->set(0, Smi::FromInt(0));
} else {
array->set(0, *name);
}
InstallHandlers(1, types, handlers);
InstallHandlers(1, maps, handlers);
}

View File

@ -262,7 +262,7 @@ class FeedbackNexus {
}
Handle<FixedArray> EnsureArrayOfSize(int length);
void InstallHandlers(int start_index, TypeHandleList* types,
void InstallHandlers(int start_index, MapHandleList* maps,
CodeHandleList* handlers);
int ExtractMaps(int start_index, MapHandleList* maps) const;
MaybeHandle<Code> FindHandlerForMap(int start_index, Handle<Map> map) const;
@ -329,9 +329,9 @@ class LoadICNexus : public FeedbackNexus {
void ConfigureMegamorphic();
void ConfigurePremonomorphic();
void ConfigureMonomorphic(Handle<HeapType> type, Handle<Code> handler);
void ConfigureMonomorphic(Handle<Map> receiver_map, Handle<Code> handler);
void ConfigurePolymorphic(TypeHandleList* types, CodeHandleList* handlers);
void ConfigurePolymorphic(MapHandleList* maps, CodeHandleList* handlers);
InlineCacheState StateFromFeedback() const OVERRIDE;
int ExtractMaps(MapHandleList* maps) const OVERRIDE;
@ -357,10 +357,10 @@ class KeyedLoadICNexus : public FeedbackNexus {
void ConfigureMegamorphic();
void ConfigurePremonomorphic();
// name can be a null handle for element loads.
void ConfigureMonomorphic(Handle<Name> name, Handle<HeapType> type,
void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map,
Handle<Code> handler);
// name can be null.
void ConfigurePolymorphic(Handle<Name> name, TypeHandleList* types,
void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps,
CodeHandleList* handlers);
InlineCacheState StateFromFeedback() const OVERRIDE;