GenerateNameCheck(name, this->name(), &miss);
}
- __ JumpIfSmi(receiver(), &miss);
+ Label number_case;
+ Label* smi_target = HasHeapNumberMap(receiver_maps) ? &number_case : &miss;
+ __ JumpIfSmi(receiver(), smi_target);
+
Register map_reg = scratch1();
int receiver_count = receiver_maps->length();
int number_of_handled_maps = 0;
__ ldr(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset));
+ Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
for (int current = 0; current < receiver_count; ++current) {
Handle<Map> map = receiver_maps->at(current);
if (!map->is_deprecated()) {
number_of_handled_maps++;
__ mov(ip, Operand(receiver_maps->at(current)));
__ cmp(map_reg, ip);
+ if (map.is_identical_to(heap_number_map)) {
+ ASSERT(!number_case.is_unused());
+ __ bind(&number_case);
+ }
__ Jump(handlers->at(current), RelocInfo::CODE_TARGET, eq);
}
}
GenerateNameCheck(name, this->name(), &miss);
}
- __ JumpIfSmi(receiver(), &miss);
+ Label number_case;
+ Label* smi_target = HasHeapNumberMap(receiver_maps) ? &number_case : &miss;
+ __ JumpIfSmi(receiver(), smi_target);
+
Register map_reg = scratch1();
__ mov(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset));
int receiver_count = receiver_maps->length();
int number_of_handled_maps = 0;
+ Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
for (int current = 0; current < receiver_count; ++current) {
Handle<Map> map = receiver_maps->at(current);
if (!map->is_deprecated()) {
number_of_handled_maps++;
__ cmp(map_reg, map);
+ if (map.is_identical_to(heap_number_map)) {
+ ASSERT(!number_case.is_unused());
+ __ bind(&number_case);
+ }
__ j(equal, handlers->at(current));
}
}
HeapObject* IC::GetCodeCacheHolder(Isolate* isolate,
Object* object,
InlineCacheHolderFlag holder) {
- Object* map_owner =
- holder == OWN_MAP ? object : object->GetPrototype(isolate);
+ if (object->IsSmi()) holder = PROTOTYPE_MAP;
+ Object* map_owner = holder == OWN_MAP
+ ? object : object->GetPrototype(isolate);
return HeapObject::cast(map_owner);
}
}
-bool IC::UpdatePolymorphicIC(Handle<HeapObject> receiver,
+bool IC::UpdatePolymorphicIC(Handle<Object> receiver,
Handle<String> name,
Handle<Code> code) {
if (!code->is_handler()) return false;
int number_of_valid_maps;
int handler_to_overwrite = -1;
- Handle<Map> new_receiver_map(receiver->map());
+ Handle<Map> new_receiver_map(receiver->GetMarkerMap(isolate()));
target()->FindAllMaps(&receiver_maps);
int number_of_maps = receiver_maps.length();
}
-void IC::UpdateMonomorphicIC(Handle<HeapObject> receiver,
+void IC::UpdateMonomorphicIC(Handle<Object> receiver,
Handle<Code> handler,
Handle<String> name) {
if (!handler->is_handler()) return set_target(*handler);
void IC::PatchCache(Handle<Object> object,
Handle<String> name,
Handle<Code> code) {
- // TODO(verwaest): Handle smi here as well.
- if (!object->IsHeapObject()) return;
-
- Handle<HeapObject> receiver = Handle<HeapObject>::cast(object);
switch (state()) {
case UNINITIALIZED:
case PREMONOMORPHIC:
case MONOMORPHIC_PROTOTYPE_FAILURE:
- UpdateMonomorphicIC(receiver, code, name);
+ UpdateMonomorphicIC(object, code, name);
break;
- case MONOMORPHIC:
+ case MONOMORPHIC: {
// For now, call stubs are allowed to rewrite to the same stub. This
// happens e.g., when the field does not contain a function.
ASSERT(target()->is_call_stub() ||
target()->is_keyed_call_stub() ||
!target().is_identical_to(code));
- if (!target()->is_keyed_stub()) {
- bool is_same_handler = false;
- Code* old_handler = target()->FindFirstHandler();
- is_same_handler = old_handler == *code;
-
- if (is_same_handler &&
- IsTransitionedMapOfMonomorphicTarget(receiver->map())) {
- UpdateMonomorphicIC(receiver, code, name);
- break;
- }
+ Code* old_handler = target()->FindFirstHandler();
+ if (old_handler == *code &&
+ IsTransitionedMapOfMonomorphicTarget(
+ object->GetMarkerMap(isolate()))) {
+ UpdateMonomorphicIC(object, code, name);
+ break;
}
// Fall through.
+ }
case POLYMORPHIC:
if (!target()->is_keyed_stub()) {
- if (UpdatePolymorphicIC(receiver, name, code)) break;
+ if (UpdatePolymorphicIC(object, name, code)) break;
CopyICToMegamorphicCache(name);
}
set_target(*megamorphic_stub());
// Fall through.
case MEGAMORPHIC:
- UpdateMegamorphicCache(receiver->map(), *name, *code);
+ UpdateMegamorphicCache(object->GetMarkerMap(isolate()), *name, *code);
break;
case DEBUG_STUB:
break;
UNREACHABLE();
return Handle<Code>::null();
}
- void UpdateMonomorphicIC(Handle<HeapObject> receiver,
+ void UpdateMonomorphicIC(Handle<Object> receiver,
Handle<Code> handler,
Handle<String> name);
- bool UpdatePolymorphicIC(Handle<HeapObject> receiver,
+ bool UpdatePolymorphicIC(Handle<Object> receiver,
Handle<String> name,
Handle<Code> code);
}
+Map* Object::GetMarkerMap(Isolate* isolate) {
+ if (IsSmi()) return isolate->heap()->heap_number_map();
+ return HeapObject::cast(this)->map();
+}
+
+
Object* Object::GetHash() {
// The object is either a number, a name, an odd-ball,
// a real JS object, or a Harmony proxy.
// Return the object's prototype (might be Heap::null_value()).
Object* GetPrototype(Isolate* isolate);
+ Map* GetMarkerMap(Isolate* isolate);
// Returns the permanent hash code associated with this object. May return
// undefined if not yet created.
Handle<Code> StubCache::ComputeMonomorphicIC(Handle<Name> name,
- Handle<HeapObject> object,
+ Handle<Object> object,
Handle<Code> handler,
StrictModeFlag strict_mode) {
Code::Kind kind = handler->handler_kind();
name, stub_holder_map, kind, strict_mode, cache_holder);
if (!ic.is_null()) return ic;
- Handle<Map> map(object->map());
+ Handle<Map> map(object->GetMarkerMap(isolate()));
if (kind == Code::LOAD_IC) {
LoadStubCompiler ic_compiler(isolate(), cache_holder);
ic = ic_compiler.CompileMonomorphicIC(map, handler, name);
}
+bool BaseLoadStoreStubCompiler::HasHeapNumberMap(MapHandleList* receiver_maps) {
+ for (int i = 0; i < receiver_maps->length(); ++i) {
+ Handle<Map> map = receiver_maps->at(i);
+ if (map.is_identical_to(isolate()->factory()->heap_number_map())) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
Register BaseLoadStoreStubCompiler::HandlerFrontend(Handle<Object> object,
Register object_reg,
Handle<JSObject> holder,
StrictModeFlag strict_mode = kNonStrictMode);
Handle<Code> ComputeMonomorphicIC(Handle<Name> name,
- Handle<HeapObject> receiver,
+ Handle<Object> receiver,
Handle<Code> handler,
StrictModeFlag strict_mode);
void InitializeRegisters();
+ bool HasHeapNumberMap(MapHandleList* receiver_maps);
+
Code::Kind kind_;
InlineCacheHolderFlag cache_holder_;
Register* registers_;
GenerateNameCheck(name, this->name(), &miss);
}
- __ JumpIfSmi(receiver(), &miss);
+ Label number_case;
+ Label* smi_target = HasHeapNumberMap(receiver_maps) ? &number_case : &miss;
+ __ JumpIfSmi(receiver(), smi_target);
+
Register map_reg = scratch1();
__ movq(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset));
int receiver_count = receiver_maps->length();
int number_of_handled_maps = 0;
+ Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
for (int current = 0; current < receiver_count; ++current) {
Handle<Map> map = receiver_maps->at(current);
if (!map->is_deprecated()) {
number_of_handled_maps++;
// Check map and tail call if there's a match
__ Cmp(map_reg, receiver_maps->at(current));
+ if (map.is_identical_to(heap_number_map)) {
+ ASSERT(!number_case.is_unused());
+ __ bind(&number_case);
+ }
__ j(equal, handlers->at(current), RelocInfo::CODE_TARGET);
}
}