// 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
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) {
// 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(
}
-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);
}
-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();
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());
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;
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_);
}
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;
JSObject::TryMigrateInstance(holder_);
}
map = Handle<Map>(holder_->map());
- if (!CanInlinePropertyAccess(ToType(map))) {
+ if (!CanInlinePropertyAccess(map)) {
lookup_.NotFound();
return false;
}
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();
}
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());
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;
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;
}
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,
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);
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;
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;
}
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 {
}
FinishCurrentBlock(compare);
- if (info.type()->Is(Type::Number())) {
+ if (info.IsNumberType()) {
GotoNoSimulate(if_true, number_block);
if_true = number_block;
}
// 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 {
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;
}
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) {
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;
}
}
} 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;
}
if (monomorphic) {
- Handle<Map> map = types->first();
+ Handle<Map> map = maps->first();
if (!CanInlineElementAccess(map)) {
instr = AddInstruction(BuildKeyedGeneric(access_type, expr, obj, key,
val));
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() &&
Handle<String> name,
HValue* value,
bool is_uninitialized) {
- SmallMapList* types;
- ComputeReceiverTypes(expr, object, &types, zone());
- DCHECK(types != 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);
+ SmallMapList* maps;
+ ComputeReceiverTypes(expr, object, &maps, zone());
+ DCHECK(maps != NULL);
+
+ 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);
}
-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];
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);
std::sort(order, order + ordered_functions);
- if (i < types->length()) {
- types->Clear();
+ if (i < maps->length()) {
+ maps->Clear();
ordered_functions = -1;
}
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;
}
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;
}
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();
// 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();
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;
}
}
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) {
}
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.
AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT
- Type* ToType(Handle<Map> map);
-
private:
// Helpers for flow graph construction.
enum GlobalPropertyAccess {
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
// 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 {
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());
}
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(); }
LookupResult lookup_;
HOptimizedGraphBuilder* builder_;
PropertyAccessType access_type_;
- Type* type_;
+ Handle<Map> map_;
Handle<String> name_;
Handle<JSObject> holder_;
Handle<JSFunction> accessor_;
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
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));
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
// -----------------------------------
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));
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));
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;
#define __ ACCESS_MASM(masm())
-Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types,
+Handle<Code> PropertyICCompiler::CompilePolymorphic(MapHandleList* maps,
CodeHandleList* handlers,
Handle<Name> name,
Code::StubType type,
}
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
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);
}
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
// -----------------------------------
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));
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);
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));
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));
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;
#define __ ACCESS_MASM(masm())
-Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types,
+Handle<Code> PropertyICCompiler::CompilePolymorphic(MapHandleList* maps,
CodeHandleList* handlers,
Handle<Name> name,
Code::StubType type,
}
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
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);
}
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) {
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);
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
}
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
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;
}
-void PropertyHandlerCompiler::set_type_for_object(Handle<Object> object) {
- type_ = IC::CurrentTypeOf(object, isolate());
-}
-
-
#define __ ACCESS_MASM(masm())
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;
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();
}
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());
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 {
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);
}
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(),
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);
}
}
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;
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());
}
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);
}
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);
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() {}
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() {}
// 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,
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() {}
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);
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() {}
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);
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));
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
// -----------------------------------
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;
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));
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());
#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,
}
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
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);
}
}
-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())) {
}
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 =
// 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;
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;
}
-// 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();
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();
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);
}
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,
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);
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);
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;
}
-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());
}
-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;
}
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,
// 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());
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;
}
-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;
}
-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;
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());
}
}
}
-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));
}
}
}
// 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;
} 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 {
}
-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);
}
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,
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;
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);
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()) {
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,
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;
}
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);
}
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());
}
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);
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);
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;
}
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;
}
}
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());
}
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()) {
}
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(),
lookup->representation());
return stub.GetCode();
}
- NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
+ NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
return compiler.CompileStoreField(lookup);
}
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) {
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)) ||
// 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);
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);
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) {
}
}
- 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;
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_;
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
// -----------------------------------
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));
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
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));
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));
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<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types,
+Handle<Code> PropertyICCompiler::CompilePolymorphic(MapHandleList* maps,
CodeHandleList* handlers,
Handle<Name> name,
Code::StubType type,
}
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
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);
}
}
-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);
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)
}
-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));
}
-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);
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 {
}
-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);
}
}
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;
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;
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;