Commit e149f81e authored by dslomov@chromium.org's avatar dslomov@chromium.org

Keyed stores to super with numeric keys.

R=verwaest@chromium.org, arv@chromium.org, ishell@chromium.org
BUG=v8:3330
LOG=N

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24696 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 8854589c
...@@ -802,6 +802,82 @@ MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate, ...@@ -802,6 +802,82 @@ MaybeHandle<Object> Object::GetElementWithReceiver(Isolate* isolate,
} }
MaybeHandle<Object> Object::SetElementWithReceiver(
Isolate* isolate, Handle<Object> object, Handle<Object> receiver,
uint32_t index, Handle<Object> value, StrictMode strict_mode) {
// Iterate up the prototype chain until an element is found or the null
// prototype is encountered.
bool done = false;
for (PrototypeIterator iter(isolate, object,
object->IsJSProxy() || object->IsJSObject()
? PrototypeIterator::START_AT_RECEIVER
: PrototypeIterator::START_AT_PROTOTYPE);
!iter.IsAtEnd() && !done; iter.Advance()) {
if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
// TODO(dslomov): implement.
isolate->ThrowIllegalOperation();
return MaybeHandle<Object>();
}
Handle<JSObject> js_object =
Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
// Check access rights if needed.
if (js_object->IsAccessCheckNeeded()) {
if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_SET)) {
isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_SET);
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
return isolate->factory()->undefined_value();
}
}
if (js_object->HasIndexedInterceptor()) {
Maybe<PropertyAttributes> from_interceptor =
JSObject::GetElementAttributeFromInterceptor(js_object, receiver,
index);
if (!from_interceptor.has_value) return MaybeHandle<Object>();
if ((from_interceptor.value & READ_ONLY) != 0) {
return WriteToReadOnlyElement(isolate, receiver, index, value,
strict_mode);
}
done = from_interceptor.value != ABSENT;
}
if (!done &&
js_object->elements() != isolate->heap()->empty_fixed_array()) {
ElementsAccessor* accessor = js_object->GetElementsAccessor();
PropertyAttributes attrs =
accessor->GetAttributes(receiver, js_object, index);
if ((attrs & READ_ONLY) != 0) {
return WriteToReadOnlyElement(isolate, receiver, index, value,
strict_mode);
}
Handle<AccessorPair> accessor_pair;
if (accessor->GetAccessorPair(receiver, js_object, index)
.ToHandle(&accessor_pair)) {
return JSObject::SetElementWithCallback(receiver, accessor_pair, index,
value, js_object, strict_mode);
} else {
done = attrs != ABSENT;
}
}
}
if (!receiver->IsJSObject()) {
return WriteToReadOnlyElement(isolate, receiver, index, value, strict_mode);
}
Handle<JSObject> target = Handle<JSObject>::cast(receiver);
ElementsAccessor* accessor = target->GetElementsAccessor();
PropertyAttributes attrs = accessor->GetAttributes(receiver, target, index);
if ((attrs & READ_ONLY) != 0) {
return WriteToReadOnlyElement(isolate, receiver, index, value, strict_mode);
}
PropertyAttributes new_attrs = attrs != ABSENT ? attrs : NONE;
return JSObject::SetElement(target, index, value, new_attrs, strict_mode,
false);
}
Map* Object::GetRootMap(Isolate* isolate) { Map* Object::GetRootMap(Isolate* isolate) {
DisallowHeapAllocation no_alloc; DisallowHeapAllocation no_alloc;
if (IsSmi()) { if (IsSmi()) {
...@@ -2932,6 +3008,21 @@ MaybeHandle<Object> Object::WriteToReadOnlyProperty(LookupIterator* it, ...@@ -2932,6 +3008,21 @@ MaybeHandle<Object> Object::WriteToReadOnlyProperty(LookupIterator* it,
} }
MaybeHandle<Object> Object::WriteToReadOnlyElement(Isolate* isolate,
Handle<Object> receiver,
uint32_t index,
Handle<Object> value,
StrictMode strict_mode) {
if (strict_mode != STRICT) return value;
Handle<Object> args[] = {isolate->factory()->NewNumberFromUint(index),
receiver};
THROW_NEW_ERROR(isolate, NewTypeError("strict_read_only_property",
HandleVector(args, arraysize(args))),
Object);
}
MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it, MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it,
Handle<Object> value) { Handle<Object> value) {
// Proxies are handled on the WithHandler path. Other non-JSObjects cannot // Proxies are handled on the WithHandler path. Other non-JSObjects cannot
...@@ -4075,6 +4166,21 @@ Maybe<PropertyAttributes> JSObject::GetElementAttributeWithInterceptor( ...@@ -4075,6 +4166,21 @@ Maybe<PropertyAttributes> JSObject::GetElementAttributeWithInterceptor(
// callbacks or interceptor calls. // callbacks or interceptor calls.
AssertNoContextChange ncc(isolate); AssertNoContextChange ncc(isolate);
Maybe<PropertyAttributes> from_interceptor =
GetElementAttributeFromInterceptor(object, receiver, index);
if (!from_interceptor.has_value) return Maybe<PropertyAttributes>();
if (from_interceptor.value != ABSENT) return maybe(from_interceptor.value);
return GetElementAttributeWithoutInterceptor(object, receiver, index,
check_prototype);
}
Maybe<PropertyAttributes> JSObject::GetElementAttributeFromInterceptor(
Handle<JSObject> object, Handle<Object> receiver, uint32_t index) {
Isolate* isolate = object->GetIsolate();
AssertNoContextChange ncc(isolate);
Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor()); Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
PropertyCallbackArguments args( PropertyCallbackArguments args(
isolate, interceptor->data(), *receiver, *object); isolate, interceptor->data(), *receiver, *object);
...@@ -4095,9 +4201,8 @@ Maybe<PropertyAttributes> JSObject::GetElementAttributeWithInterceptor( ...@@ -4095,9 +4201,8 @@ Maybe<PropertyAttributes> JSObject::GetElementAttributeWithInterceptor(
v8::Handle<v8::Value> result = args.Call(getter, index); v8::Handle<v8::Value> result = args.Call(getter, index);
if (!result.IsEmpty()) return maybe(NONE); if (!result.IsEmpty()) return maybe(NONE);
} }
RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe<PropertyAttributes>());
return GetElementAttributeWithoutInterceptor( return maybe(ABSENT);
object, receiver, index, check_prototype);
} }
...@@ -11867,13 +11972,10 @@ MaybeHandle<Object> JSObject::GetElementWithCallback( ...@@ -11867,13 +11972,10 @@ MaybeHandle<Object> JSObject::GetElementWithCallback(
} }
MaybeHandle<Object> JSObject::SetElementWithCallback(Handle<JSObject> object, MaybeHandle<Object> JSObject::SetElementWithCallback(
Handle<Object> structure, Handle<Object> object, Handle<Object> structure, uint32_t index,
uint32_t index, Handle<Object> value, Handle<JSObject> holder, StrictMode strict_mode) {
Handle<Object> value, Isolate* isolate = holder->GetIsolate();
Handle<JSObject> holder,
StrictMode strict_mode) {
Isolate* isolate = object->GetIsolate();
// We should never get here to initialize a const with the hole // We should never get here to initialize a const with the hole
// value since a const declaration would conflict with the setter. // value since a const declaration would conflict with the setter.
...@@ -11889,7 +11991,7 @@ MaybeHandle<Object> JSObject::SetElementWithCallback(Handle<JSObject> object, ...@@ -11889,7 +11991,7 @@ MaybeHandle<Object> JSObject::SetElementWithCallback(Handle<JSObject> object,
if (call_fun == NULL) return value; if (call_fun == NULL) return value;
Handle<Object> number = isolate->factory()->NewNumberFromUint(index); Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
Handle<String> key(isolate->factory()->NumberToString(number)); Handle<String> key(isolate->factory()->NumberToString(number));
LOG(isolate, ApiNamedPropertyAccess("store", *object, *key)); LOG(isolate, ApiNamedPropertyAccess("store", *holder, *key));
PropertyCallbackArguments PropertyCallbackArguments
args(isolate, data->data(), *object, *holder); args(isolate, data->data(), *object, *holder);
args.Call(call_fun, args.Call(call_fun,
......
...@@ -1131,6 +1131,9 @@ class Object { ...@@ -1131,6 +1131,9 @@ class Object {
StorePropertyMode data_store_mode = NORMAL_PROPERTY); StorePropertyMode data_store_mode = NORMAL_PROPERTY);
MUST_USE_RESULT static MaybeHandle<Object> WriteToReadOnlyProperty( MUST_USE_RESULT static MaybeHandle<Object> WriteToReadOnlyProperty(
LookupIterator* it, Handle<Object> value, StrictMode strict_mode); LookupIterator* it, Handle<Object> value, StrictMode strict_mode);
MUST_USE_RESULT static MaybeHandle<Object> WriteToReadOnlyElement(
Isolate* isolate, Handle<Object> receiver, uint32_t index,
Handle<Object> value, StrictMode strict_mode);
MUST_USE_RESULT static MaybeHandle<Object> SetDataProperty( MUST_USE_RESULT static MaybeHandle<Object> SetDataProperty(
LookupIterator* it, Handle<Object> value); LookupIterator* it, Handle<Object> value);
MUST_USE_RESULT static MaybeHandle<Object> AddDataProperty( MUST_USE_RESULT static MaybeHandle<Object> AddDataProperty(
...@@ -1176,6 +1179,10 @@ class Object { ...@@ -1176,6 +1179,10 @@ class Object {
Handle<Object> receiver, Handle<Object> receiver,
uint32_t index); uint32_t index);
MUST_USE_RESULT static MaybeHandle<Object> SetElementWithReceiver(
Isolate* isolate, Handle<Object> object, Handle<Object> receiver,
uint32_t index, Handle<Object> value, StrictMode strict_mode);
static inline Handle<Object> GetPrototypeSkipHiddenPrototypes( static inline Handle<Object> GetPrototypeSkipHiddenPrototypes(
Isolate* isolate, Handle<Object> receiver); Isolate* isolate, Handle<Object> receiver);
...@@ -1927,8 +1934,7 @@ class JSObject: public JSReceiver { ...@@ -1927,8 +1934,7 @@ class JSObject: public JSReceiver {
// These methods do not perform access checks! // These methods do not perform access checks!
MUST_USE_RESULT static MaybeHandle<AccessorPair> GetOwnElementAccessorPair( MUST_USE_RESULT static MaybeHandle<AccessorPair> GetOwnElementAccessorPair(
Handle<JSObject> object, Handle<JSObject> object, uint32_t index);
uint32_t index);
MUST_USE_RESULT static MaybeHandle<Object> SetFastElement( MUST_USE_RESULT static MaybeHandle<Object> SetFastElement(
Handle<JSObject> object, Handle<JSObject> object,
...@@ -2253,18 +2259,30 @@ class JSObject: public JSReceiver { ...@@ -2253,18 +2259,30 @@ class JSObject: public JSReceiver {
GetElementAttributeWithInterceptor(Handle<JSObject> object, GetElementAttributeWithInterceptor(Handle<JSObject> object,
Handle<JSReceiver> receiver, Handle<JSReceiver> receiver,
uint32_t index, bool continue_search); uint32_t index, bool continue_search);
// Queries indexed interceptor on an object for property attributes.
//
// We determine property attributes as follows:
// - if interceptor has a query callback, then the property attributes are
// the result of query callback for index.
// - otherwise if interceptor has a getter callback and it returns
// non-empty value on index, then the property attributes is NONE
// (property is present, and it is enumerable, configurable, writable)
// - otherwise there are no property attributes that can be inferred for
// interceptor, and this function returns ABSENT.
MUST_USE_RESULT static Maybe<PropertyAttributes>
GetElementAttributeFromInterceptor(Handle<JSObject> object,
Handle<Object> receiver,
uint32_t index);
MUST_USE_RESULT static Maybe<PropertyAttributes> MUST_USE_RESULT static Maybe<PropertyAttributes>
GetElementAttributeWithoutInterceptor(Handle<JSObject> object, GetElementAttributeWithoutInterceptor(Handle<JSObject> object,
Handle<JSReceiver> receiver, Handle<JSReceiver> receiver,
uint32_t index, uint32_t index,
bool continue_search); bool continue_search);
MUST_USE_RESULT static MaybeHandle<Object> SetElementWithCallback( MUST_USE_RESULT static MaybeHandle<Object> SetElementWithCallback(
Handle<JSObject> object, Handle<Object> object, Handle<Object> structure, uint32_t index,
Handle<Object> structure, Handle<Object> value, Handle<JSObject> holder, StrictMode strict_mode);
uint32_t index,
Handle<Object> value,
Handle<JSObject> holder,
StrictMode strict_mode);
MUST_USE_RESULT static MaybeHandle<Object> SetElementWithInterceptor( MUST_USE_RESULT static MaybeHandle<Object> SetElementWithInterceptor(
Handle<JSObject> object, Handle<JSObject> object,
uint32_t index, uint32_t index,
......
...@@ -287,6 +287,30 @@ static Object* StoreToSuper(Isolate* isolate, Handle<JSObject> home_object, ...@@ -287,6 +287,30 @@ static Object* StoreToSuper(Isolate* isolate, Handle<JSObject> home_object,
} }
static Object* StoreElementToSuper(Isolate* isolate,
Handle<JSObject> home_object,
Handle<Object> receiver, uint32_t index,
Handle<Object> value,
StrictMode strict_mode) {
if (home_object->IsAccessCheckNeeded() &&
!isolate->MayIndexedAccess(home_object, index, v8::ACCESS_SET)) {
isolate->ReportFailedAccessCheck(home_object, v8::ACCESS_SET);
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
}
PrototypeIterator iter(isolate, home_object);
Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
if (!proto->IsJSReceiver()) return isolate->heap()->undefined_value();
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
Object::SetElementWithReceiver(isolate, proto, receiver, index, value,
strict_mode));
return *result;
}
RUNTIME_FUNCTION(Runtime_StoreToSuper_Strict) { RUNTIME_FUNCTION(Runtime_StoreToSuper_Strict) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK(args.length() == 4); DCHECK(args.length() == 4);
...@@ -314,13 +338,18 @@ RUNTIME_FUNCTION(Runtime_StoreToSuper_Sloppy) { ...@@ -314,13 +338,18 @@ RUNTIME_FUNCTION(Runtime_StoreToSuper_Sloppy) {
static Object* StoreKeyedToSuper(Isolate* isolate, Handle<JSObject> home_object, static Object* StoreKeyedToSuper(Isolate* isolate, Handle<JSObject> home_object,
Handle<Object> receiver, Handle<Object> key, Handle<Object> receiver, Handle<Object> key,
Handle<Object> value, StrictMode strict_mode) { Handle<Object> value, StrictMode strict_mode) {
uint32_t index;
if (key->ToArrayIndex(&index)) {
return StoreElementToSuper(isolate, home_object, receiver, index, value,
strict_mode);
}
Handle<Name> name; Handle<Name> name;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name, ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
Runtime::ToName(isolate, key)); Runtime::ToName(isolate, key));
uint32_t index;
if (name->AsArrayIndex(&index)) { if (name->AsArrayIndex(&index)) {
// TODO(dslomov): Implement. return StoreElementToSuper(isolate, home_object, receiver, index, value,
return ThrowUnsupportedSuper(isolate); strict_mode);
} }
return StoreToSuper(isolate, home_object, receiver, name, value, strict_mode); return StoreToSuper(isolate, home_object, receiver, name, value, strict_mode);
} }
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment