if (object->IsJSFunction()) return heap->closure_string();
String* constructor_name = object->constructor_name();
if (constructor_name == heap->Object_string()) {
- // Look up an immediate "constructor" property, if it is a function,
- // return its name. This is for instances of binding objects, which
- // have prototype constructor type "Object".
- Object* constructor_prop = NULL;
- Isolate* isolate = heap->isolate();
- LookupResult result(isolate);
- object->LookupOwnRealNamedProperty(
- isolate->factory()->constructor_string(), &result);
- if (!result.IsFound()) return object->constructor_name();
-
- constructor_prop = result.GetLazyValue();
- if (constructor_prop->IsJSFunction()) {
- Object* maybe_name =
- JSFunction::cast(constructor_prop)->shared()->name();
- if (maybe_name->IsString()) {
- String* name = String::cast(maybe_name);
- if (name->length() > 0) return name;
- }
- }
+ // TODO(verwaest): Try to get object.constructor.name in this case.
+ // This requires handlification of the V8HeapExplorer.
}
return object->constructor_name();
}
HConstant::cast(checked_object->ActualValue())->handle(isolate()));
if (object->IsJSObject()) {
- LookupResult lookup(isolate());
- Handle<JSObject>::cast(object)->Lookup(info->name(), &lookup);
- Handle<Object> value(lookup.GetLazyValue(), isolate());
-
- DCHECK(!value->IsTheHole());
+ LookupIterator it(object, info->name(), LookupIterator::CHECK_PROPERTY);
+ Handle<Object> value = JSObject::GetDataProperty(&it);
+ CHECK(it.IsFound());
return New<HConstant>(value);
}
}
!current_info()->global_object()->IsAccessCheckNeeded()) {
Handle<String> name = proxy->name();
Handle<GlobalObject> global(current_info()->global_object());
- LookupResult lookup(isolate());
- global->Lookup(name, &lookup);
- if (lookup.IsNormal() && lookup.GetValue()->IsJSFunction()) {
- Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue()));
+ LookupIterator it(global, name, LookupIterator::CHECK_PROPERTY);
+ Handle<Object> value = JSObject::GetDataProperty(&it);
+ if (it.IsFound() && value->IsJSFunction()) {
+ Handle<JSFunction> candidate = Handle<JSFunction>::cast(value);
// If the function is in new space we assume it's more likely to
// change and thus prefer the general IC code.
if (!isolate()->heap()->InNewSpace(*candidate)) {
DCHECK(holder.is_identical_to(receiver));
return isolate()->builtins()->StoreIC_Normal();
case CALLBACKS: {
- Handle<Object> callback(lookup->GetCallbackObject(), isolate());
+ if (!holder->HasFastProperties()) break;
+ Handle<Object> callback(lookup->GetValueFromMap(holder->map()),
+ isolate());
if (callback->IsExecutableAccessorInfo()) {
Handle<ExecutableAccessorInfo> info =
Handle<ExecutableAccessorInfo>::cast(callback);
if (v8::ToCData<Address>(info->setter()) == 0) break;
- if (!holder->HasFastProperties()) break;
if (!ExecutableAccessorInfo::IsCompatibleReceiverType(
isolate(), info, receiver_type())) {
break;
Handle<Object> setter(
Handle<AccessorPair>::cast(callback)->setter(), isolate());
if (!setter->IsJSFunction()) break;
- if (holder->IsGlobalObject()) break;
- if (!holder->HasFastProperties()) break;
Handle<JSFunction> function = Handle<JSFunction>::cast(setter);
CallOptimization call_optimization(function);
NamedStoreHandlerCompiler compiler(isolate(), receiver_type(),
Handle<Object> JSObject::GetDataProperty(Handle<JSObject> object,
Handle<Name> key) {
LookupIterator it(object, key, LookupIterator::CHECK_DERIVED_PROPERTY);
- for (; it.IsFound(); it.Next()) {
- switch (it.state()) {
+ return GetDataProperty(&it);
+}
+
+
+Handle<Object> JSObject::GetDataProperty(LookupIterator* it) {
+ for (; it->IsFound(); it->Next()) {
+ switch (it->state()) {
case LookupIterator::NOT_FOUND:
case LookupIterator::ACCESS_CHECK:
case LookupIterator::INTERCEPTOR:
UNREACHABLE();
case LookupIterator::JSPROXY:
- return it.isolate()->factory()->undefined_value();
+ it->NotFound();
+ return it->isolate()->factory()->undefined_value();
case LookupIterator::PROPERTY:
- if (!it.HasProperty()) continue;
- switch (it.property_kind()) {
+ if (!it->HasProperty()) continue;
+ switch (it->property_kind()) {
case LookupIterator::DATA:
- return it.GetDataValue();
+ return it->GetDataValue();
case LookupIterator::ACCESSOR:
// TODO(verwaest): For now this doesn't call into
// ExecutableAccessorInfo, since clients don't need it. Update once
// relevant.
- return it.isolate()->factory()->undefined_value();
+ it->NotFound();
+ return it->isolate()->factory()->undefined_value();
}
}
}
- return it.isolate()->factory()->undefined_value();
+ return it->isolate()->factory()->undefined_value();
}
}
-Object* JSObject::GetNormalizedProperty(const LookupResult* result) {
- DCHECK(!HasFastProperties());
- Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
- if (IsGlobalObject()) {
- value = PropertyCell::cast(value)->value();
- }
- DCHECK(!value->IsPropertyCell() && !value->IsCell());
- return value;
-}
-
-
void JSObject::SetNormalizedProperty(Handle<JSObject> object,
Handle<Name> name,
Handle<Object> value,
}
} else {
Isolate* isolate = GetIsolate();
- LookupResult result(isolate);
- LookupOwnRealNamedProperty(isolate->factory()->hidden_string(), &result);
- if (result.IsFound()) {
- DCHECK(result.IsNormal());
- DCHECK(result.holder() == this);
- return GetNormalizedProperty(&result);
+ LookupIterator it(handle(this), isolate->factory()->hidden_string(),
+ LookupIterator::CHECK_PROPERTY);
+ if (it.IsFound() && it.HasProperty()) {
+ DCHECK_EQ(LookupIterator::DATA, it.property_kind());
+ return *it.GetDataValue();
}
return GetHeap()->undefined_value();
}
// or returns false if such a map is not yet available.
static bool TryMigrateInstance(Handle<JSObject> instance);
- // Retrieve a value in a normalized object given a lookup result.
- // Handles the special representation of JS global objects.
- Object* GetNormalizedProperty(const LookupResult* result);
-
// Sets the property value in a normalized object given (key, value, details).
// Handles the special representation of JS global objects.
static void SetNormalizedProperty(Handle<JSObject> object,
static Handle<Object> GetDataProperty(Handle<JSObject> object,
Handle<Name> key);
+ static Handle<Object> GetDataProperty(LookupIterator* it);
DECLARE_CAST(JSObject)
return os << " -type = normal\n"
<< " -entry = " << r.GetDictionaryEntry() << "\n";
case CONSTANT:
- return os << " -type = constant\n"
- << " -value:\n" << Brief(r.GetConstant()) << "\n";
+ return os << " -type = constant\n";
case FIELD:
os << " -type = field\n"
<< " -index = " << r.GetFieldIndex().property_index() << "\n"
r.GetFieldType()->PrintTo(os);
return os << "\n";
case CALLBACKS:
- return os << " -type = call backs\n"
- << " -callback object:\n" << Brief(r.GetCallbackObject());
+ return os << " -type = call backs\n";
case HANDLER:
return os << " -type = lookup proxy\n";
case INTERCEPTOR:
case FIELD:
return value->FitsRepresentation(representation()) &&
GetFieldType()->NowContains(value);
- case CONSTANT:
- DCHECK(GetConstant() != *value ||
+ case CONSTANT: {
+ Map* map =
+ lookup_type_ == DESCRIPTOR_TYPE ? holder_->map() : transition_;
+ Object* constant = GetConstantFromMap(map);
+ DCHECK(constant != *value ||
value->FitsRepresentation(representation()));
- return GetConstant() == *value;
+ return constant == *value;
+ }
case CALLBACKS:
case HANDLER:
case INTERCEPTOR:
return IsDescriptorOrDictionary() && type() == CONSTANT;
}
- bool IsConstantFunction() const {
- return IsConstant() && GetConstant()->IsJSFunction();
- }
-
bool IsDontDelete() const { return details_.IsDontDelete(); }
bool IsDontEnum() const { return details_.IsDontEnum(); }
bool IsFound() const { return lookup_type_ != NOT_FOUND; }
return IsFound() && !IsTransition();
}
- bool IsDataProperty() const {
- switch (lookup_type_) {
- case NOT_FOUND:
- case TRANSITION_TYPE:
- case HANDLER_TYPE:
- case INTERCEPTOR_TYPE:
- return false;
-
- case DESCRIPTOR_TYPE:
- case DICTIONARY_TYPE:
- switch (type()) {
- case FIELD:
- case NORMAL:
- case CONSTANT:
- return true;
- case CALLBACKS: {
- Object* callback = GetCallbackObject();
- DCHECK(!callback->IsForeign());
- return callback->IsAccessorInfo();
- }
- case HANDLER:
- case INTERCEPTOR:
- case NONEXISTENT:
- UNREACHABLE();
- return false;
- }
- }
- UNREACHABLE();
- return false;
- }
-
bool IsCacheable() const { return cacheable_; }
void DisallowCaching() { cacheable_ = false; }
- Object* GetLazyValue() const {
- switch (lookup_type_) {
- case NOT_FOUND:
- case TRANSITION_TYPE:
- case HANDLER_TYPE:
- case INTERCEPTOR_TYPE:
- return isolate()->heap()->the_hole_value();
-
- case DESCRIPTOR_TYPE:
- case DICTIONARY_TYPE:
- switch (type()) {
- case FIELD:
- return holder()->RawFastPropertyAt(GetFieldIndex());
- case NORMAL: {
- Object* value = holder()->property_dictionary()->ValueAt(
- GetDictionaryEntry());
- if (holder()->IsGlobalObject()) {
- value = PropertyCell::cast(value)->value();
- }
- return value;
- }
- case CONSTANT:
- return GetConstant();
- case CALLBACKS:
- return isolate()->heap()->the_hole_value();
- case HANDLER:
- case INTERCEPTOR:
- case NONEXISTENT:
- UNREACHABLE();
- return NULL;
- }
- }
- UNREACHABLE();
- return NULL;
- }
-
Map* GetTransitionTarget() const {
DCHECK(IsTransition());
return transition_;
return number_;
}
- JSFunction* GetConstantFunction() const {
- DCHECK(type() == CONSTANT);
- return JSFunction::cast(GetValue());
- }
-
Object* GetConstantFromMap(Map* map) const {
DCHECK(type() == CONSTANT);
return GetValueFromMap(map);
}
- JSFunction* GetConstantFunctionFromMap(Map* map) const {
- return JSFunction::cast(GetConstantFromMap(map));
- }
-
- Object* GetConstant() const {
- DCHECK(type() == CONSTANT);
- return GetValue();
- }
-
- Object* GetCallbackObject() const {
- DCHECK(!IsTransition());
- DCHECK(type() == CALLBACKS);
- return GetValue();
- }
-
- Object* GetValue() const {
- if (lookup_type_ == DESCRIPTOR_TYPE) {
- return GetValueFromMap(holder()->map());
- } else if (lookup_type_ == TRANSITION_TYPE) {
- return GetValueFromMap(transition_);
- }
- // In the dictionary case, the data is held in the value field.
- DCHECK(lookup_type_ == DICTIONARY_TYPE);
- return holder()->GetNormalizedProperty(this);
- }
-
Object* GetValueFromMap(Map* map) const {
DCHECK(lookup_type_ == DESCRIPTOR_TYPE ||
lookup_type_ == TRANSITION_TYPE);
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
i::LookupResult lookup(i_isolate);
i::Handle<i::String> name(v8::Utils::OpenHandle(*v8_str("length")));
- a->LookupOwnRealNamedProperty(name, &lookup);
- CHECK(lookup.IsPropertyCallbacks());
- i::Handle<i::Object> callback(lookup.GetCallbackObject(), i_isolate);
- CHECK(callback->IsExecutableAccessorInfo());
+ i::LookupIterator it(a, name, i::LookupIterator::CHECK_PROPERTY);
+ CHECK(it.HasProperty());
+ CHECK(it.GetAccessors()->IsExecutableAccessorInfo());
}
"Constructor2", i::V8HeapExplorer::GetConstructorName(*js_obj2)));
v8::Local<v8::Object> obj3 = js_global->Get(v8_str("obj3")).As<v8::Object>();
i::Handle<i::JSObject> js_obj3 = v8::Utils::OpenHandle(*obj3);
- CHECK_EQ(0, StringCmp(
- "Constructor3", i::V8HeapExplorer::GetConstructorName(*js_obj3)));
+ // TODO(verwaest): Restore to Constructor3 once supported by the
+ // heap-snapshot-generator.
+ CHECK_EQ(
+ 0, StringCmp("Object", i::V8HeapExplorer::GetConstructorName(*js_obj3)));
v8::Local<v8::Object> obj4 = js_global->Get(v8_str("obj4")).As<v8::Object>();
i::Handle<i::JSObject> js_obj4 = v8::Utils::OpenHandle(*obj4);
- CHECK_EQ(0, StringCmp(
- "Constructor4", i::V8HeapExplorer::GetConstructorName(*js_obj4)));
+ // TODO(verwaest): Restore to Constructor4 once supported by the
+ // heap-snapshot-generator.
+ CHECK_EQ(
+ 0, StringCmp("Object", i::V8HeapExplorer::GetConstructorName(*js_obj4)));
v8::Local<v8::Object> obj5 = js_global->Get(v8_str("obj5")).As<v8::Object>();
i::Handle<i::JSObject> js_obj5 = v8::Utils::OpenHandle(*obj5);
CHECK_EQ(0, StringCmp(