| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index 94a80f7d7a2aea73db5b600c6c21fcb1d3d2218f..92e4dc4c8c9c98f03a6267e2f393dda5c4312803 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -519,7 +519,7 @@ Handle<Object> JSProxy::SetElementWithHandler(Handle<JSProxy> proxy,
|
| Handle<JSReceiver> receiver,
|
| uint32_t index,
|
| Handle<Object> value,
|
| - StrictModeFlag strict_mode) {
|
| + StrictMode strict_mode) {
|
| Isolate* isolate = proxy->GetIsolate();
|
| Handle<String> name = isolate->factory()->Uint32ToString(index);
|
| return SetPropertyWithHandler(
|
| @@ -615,29 +615,29 @@ Handle<Object> JSObject::GetPropertyWithFailedAccessCheck(
|
|
|
| // No accessible property found.
|
| *attributes = ABSENT;
|
| - isolate->ReportFailedAccessCheck(*object, v8::ACCESS_GET);
|
| + isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_GET);
|
| RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| return isolate->factory()->undefined_value();
|
| }
|
|
|
|
|
| PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck(
|
| - Object* receiver,
|
| + Handle<JSObject> object,
|
| LookupResult* result,
|
| - Name* name,
|
| + Handle<Name> name,
|
| bool continue_search) {
|
| if (result->IsProperty()) {
|
| switch (result->type()) {
|
| case CALLBACKS: {
|
| // Only allow API accessors.
|
| - Object* obj = result->GetCallbackObject();
|
| + Handle<Object> obj(result->GetCallbackObject(), object->GetIsolate());
|
| if (obj->IsAccessorInfo()) {
|
| - AccessorInfo* info = AccessorInfo::cast(obj);
|
| + Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(obj);
|
| if (info->all_can_read()) {
|
| return result->GetAttributes();
|
| }
|
| } else if (obj->IsAccessorPair()) {
|
| - AccessorPair* pair = AccessorPair::cast(obj);
|
| + Handle<AccessorPair> pair = Handle<AccessorPair>::cast(obj);
|
| if (pair->all_can_read()) {
|
| return result->GetAttributes();
|
| }
|
| @@ -650,13 +650,11 @@ PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck(
|
| case CONSTANT: {
|
| if (!continue_search) break;
|
| // Search ALL_CAN_READ accessors in prototype chain.
|
| - LookupResult r(GetIsolate());
|
| - result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
|
| + LookupResult r(object->GetIsolate());
|
| + result->holder()->LookupRealNamedPropertyInPrototypes(*name, &r);
|
| if (r.IsProperty()) {
|
| - return GetPropertyAttributeWithFailedAccessCheck(receiver,
|
| - &r,
|
| - name,
|
| - continue_search);
|
| + return GetPropertyAttributeWithFailedAccessCheck(
|
| + object, &r, name, continue_search);
|
| }
|
| break;
|
| }
|
| @@ -664,17 +662,15 @@ PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck(
|
| case INTERCEPTOR: {
|
| // If the object has an interceptor, try real named properties.
|
| // No access check in GetPropertyAttributeWithInterceptor.
|
| - LookupResult r(GetIsolate());
|
| + LookupResult r(object->GetIsolate());
|
| if (continue_search) {
|
| - result->holder()->LookupRealNamedProperty(name, &r);
|
| + result->holder()->LookupRealNamedProperty(*name, &r);
|
| } else {
|
| - result->holder()->LocalLookupRealNamedProperty(name, &r);
|
| + result->holder()->LocalLookupRealNamedProperty(*name, &r);
|
| }
|
| if (!r.IsFound()) break;
|
| - return GetPropertyAttributeWithFailedAccessCheck(receiver,
|
| - &r,
|
| - name,
|
| - continue_search);
|
| + return GetPropertyAttributeWithFailedAccessCheck(
|
| + object, &r, name, continue_search);
|
| }
|
|
|
| case HANDLER:
|
| @@ -684,7 +680,7 @@ PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck(
|
| }
|
| }
|
|
|
| - GetIsolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
|
| + object->GetIsolate()->ReportFailedAccessCheckWrapper(object, v8::ACCESS_HAS);
|
| return ABSENT;
|
| }
|
|
|
| @@ -1280,14 +1276,13 @@ bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
|
| // - the space the existing string occupies is too small for a regular
|
| // external string.
|
| // - the existing string is in old pointer space and the backing store of
|
| - // the external string is not aligned. The GC cannot deal with fields
|
| - // containing an unaligned address that points to outside of V8's heap.
|
| + // the external string is not aligned. The GC cannot deal with a field
|
| + // containing a possibly unaligned address to outside of V8's heap.
|
| // In either case we resort to a short external string instead, omitting
|
| // the field caching the address of the backing store. When we encounter
|
| // short external strings in generated code, we need to bailout to runtime.
|
| if (size < ExternalString::kSize ||
|
| - (!IsAligned(reinterpret_cast<intptr_t>(resource->data()), kPointerSize) &&
|
| - heap->old_pointer_space()->Contains(this))) {
|
| + heap->old_pointer_space()->Contains(this)) {
|
| this->set_map_no_write_barrier(
|
| is_internalized
|
| ? (is_ascii
|
| @@ -1351,14 +1346,13 @@ bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) {
|
| // - the space the existing string occupies is too small for a regular
|
| // external string.
|
| // - the existing string is in old pointer space and the backing store of
|
| - // the external string is not aligned. The GC cannot deal with fields
|
| - // containing an unaligned address that points to outside of V8's heap.
|
| + // the external string is not aligned. The GC cannot deal with a field
|
| + // containing a possibly unaligned address to outside of V8's heap.
|
| // In either case we resort to a short external string instead, omitting
|
| // the field caching the address of the backing store. When we encounter
|
| // short external strings in generated code, we need to bailout to runtime.
|
| if (size < ExternalString::kSize ||
|
| - (!IsAligned(reinterpret_cast<intptr_t>(resource->data()), kPointerSize) &&
|
| - heap->old_pointer_space()->Contains(this))) {
|
| + heap->old_pointer_space()->Contains(this)) {
|
| this->set_map_no_write_barrier(
|
| is_internalized ? heap->short_external_ascii_internalized_string_map()
|
| : heap->short_external_ascii_string_map());
|
| @@ -1977,31 +1971,6 @@ static Handle<Object> NewStorageFor(Isolate* isolate,
|
| }
|
|
|
|
|
| -void JSObject::AddFastPropertyUsingMap(Handle<JSObject> object,
|
| - Handle<Map> new_map,
|
| - Handle<Name> name,
|
| - Handle<Object> value,
|
| - int field_index,
|
| - Representation representation) {
|
| - Isolate* isolate = object->GetIsolate();
|
| -
|
| - // This method is used to transition to a field. If we are transitioning to a
|
| - // double field, allocate new storage.
|
| - Handle<Object> storage = NewStorageFor(isolate, value, representation);
|
| -
|
| - if (object->map()->unused_property_fields() == 0) {
|
| - int new_unused = new_map->unused_property_fields();
|
| - Handle<FixedArray> properties(object->properties());
|
| - Handle<FixedArray> values = isolate->factory()->CopySizeFixedArray(
|
| - properties, properties->length() + new_unused + 1);
|
| - object->set_properties(*values);
|
| - }
|
| -
|
| - object->set_map(*new_map);
|
| - object->FastPropertyAtPut(field_index, *storage);
|
| -}
|
| -
|
| -
|
| static MaybeObject* CopyAddFieldDescriptor(Map* map,
|
| Name* name,
|
| int index,
|
| @@ -2066,7 +2035,16 @@ void JSObject::AddFastProperty(Handle<JSObject> object,
|
| Handle<Map> new_map = CopyAddFieldDescriptor(
|
| handle(object->map()), name, index, attributes, representation, flag);
|
|
|
| - AddFastPropertyUsingMap(object, new_map, name, value, index, representation);
|
| + JSObject::MigrateToMap(object, new_map);
|
| +
|
| + if (representation.IsDouble()) {
|
| + // Nothing more to be done.
|
| + if (value->IsUninitialized()) return;
|
| + HeapNumber* box = HeapNumber::cast(object->RawFastPropertyAt(index));
|
| + box->set_value(value->Number());
|
| + } else {
|
| + object->FastPropertyAtPut(index, *value);
|
| + }
|
| }
|
|
|
|
|
| @@ -2110,7 +2088,7 @@ void JSObject::AddConstantProperty(Handle<JSObject> object,
|
| Handle<Map> new_map = CopyAddConstantDescriptor(
|
| handle(object->map()), name, constant, attributes, flag);
|
|
|
| - object->set_map(*new_map);
|
| + JSObject::MigrateToMap(object, new_map);
|
| }
|
|
|
|
|
| @@ -2149,7 +2127,7 @@ Handle<Object> JSObject::AddProperty(Handle<JSObject> object,
|
| Handle<Name> name,
|
| Handle<Object> value,
|
| PropertyAttributes attributes,
|
| - StrictModeFlag strict_mode,
|
| + StrictMode strict_mode,
|
| JSReceiver::StoreFromKeyed store_mode,
|
| ExtensibilityCheck extensibility_check,
|
| ValueType value_type,
|
| @@ -2165,7 +2143,7 @@ Handle<Object> JSObject::AddProperty(Handle<JSObject> object,
|
|
|
| if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK &&
|
| !object->map()->is_extensible()) {
|
| - if (strict_mode == kNonStrictMode) {
|
| + if (strict_mode == SLOPPY) {
|
| return value;
|
| } else {
|
| Handle<Object> args[1] = { name };
|
| @@ -2199,8 +2177,7 @@ Handle<Object> JSObject::AddProperty(Handle<JSObject> object,
|
| AddSlowProperty(object, name, value, attributes);
|
| }
|
|
|
| - if (FLAG_harmony_observation &&
|
| - object->map()->is_observed() &&
|
| + if (object->map()->is_observed() &&
|
| *name != isolate->heap()->hidden_string()) {
|
| Handle<Object> old_value = isolate->factory()->the_hole_value();
|
| EnqueueChangeRecord(object, "add", name, old_value);
|
| @@ -2238,7 +2215,7 @@ Handle<Object> JSObject::SetPropertyPostInterceptor(
|
| Handle<Name> name,
|
| Handle<Object> value,
|
| PropertyAttributes attributes,
|
| - StrictModeFlag strict_mode) {
|
| + StrictMode strict_mode) {
|
| // Check local property, ignore interceptor.
|
| LookupResult result(object->GetIsolate());
|
| object->LocalLookupRealNamedProperty(*name, &result);
|
| @@ -2358,16 +2335,14 @@ bool Map::InstancesNeedRewriting(Map* target,
|
| ASSERT(target_number_of_fields >= number_of_fields);
|
| if (target_number_of_fields != number_of_fields) return true;
|
|
|
| - if (FLAG_track_double_fields) {
|
| - // If smi descriptors were replaced by double descriptors, rewrite.
|
| - DescriptorArray* old_desc = instance_descriptors();
|
| - DescriptorArray* new_desc = target->instance_descriptors();
|
| - int limit = NumberOfOwnDescriptors();
|
| - for (int i = 0; i < limit; i++) {
|
| - if (new_desc->GetDetails(i).representation().IsDouble() &&
|
| - !old_desc->GetDetails(i).representation().IsDouble()) {
|
| - return true;
|
| - }
|
| + // If smi descriptors were replaced by double descriptors, rewrite.
|
| + DescriptorArray* old_desc = instance_descriptors();
|
| + DescriptorArray* new_desc = target->instance_descriptors();
|
| + int limit = NumberOfOwnDescriptors();
|
| + for (int i = 0; i < limit; i++) {
|
| + if (new_desc->GetDetails(i).representation().IsDouble() &&
|
| + !old_desc->GetDetails(i).representation().IsDouble()) {
|
| + return true;
|
| }
|
| }
|
|
|
| @@ -2423,9 +2398,14 @@ void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) {
|
|
|
| Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
|
| Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors());
|
| - int descriptors = new_map->NumberOfOwnDescriptors();
|
| + int old_nof = old_map->NumberOfOwnDescriptors();
|
| + int new_nof = new_map->NumberOfOwnDescriptors();
|
| +
|
| + // This method only supports generalizing instances to at least the same
|
| + // number of properties.
|
| + ASSERT(old_nof <= new_nof);
|
|
|
| - for (int i = 0; i < descriptors; i++) {
|
| + for (int i = 0; i < old_nof; i++) {
|
| PropertyDetails details = new_descriptors->GetDetails(i);
|
| if (details.type() != FIELD) continue;
|
| PropertyDetails old_details = old_descriptors->GetDetails(i);
|
| @@ -2439,22 +2419,30 @@ void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) {
|
| ? old_descriptors->GetValue(i)
|
| : object->RawFastPropertyAt(old_descriptors->GetFieldIndex(i));
|
| Handle<Object> value(raw_value, isolate);
|
| - if (FLAG_track_double_fields &&
|
| - !old_details.representation().IsDouble() &&
|
| + if (!old_details.representation().IsDouble() &&
|
| details.representation().IsDouble()) {
|
| if (old_details.representation().IsNone()) {
|
| value = handle(Smi::FromInt(0), isolate);
|
| }
|
| value = NewStorageFor(isolate, value, details.representation());
|
| }
|
| - ASSERT(!(FLAG_track_double_fields &&
|
| - details.representation().IsDouble() &&
|
| - value->IsSmi()));
|
| + ASSERT(!(details.representation().IsDouble() && value->IsSmi()));
|
| int target_index = new_descriptors->GetFieldIndex(i) - inobject;
|
| if (target_index < 0) target_index += total_size;
|
| array->set(target_index, *value);
|
| }
|
|
|
| + for (int i = old_nof; i < new_nof; i++) {
|
| + PropertyDetails details = new_descriptors->GetDetails(i);
|
| + if (details.type() != FIELD) continue;
|
| + if (details.representation().IsDouble()) {
|
| + int target_index = new_descriptors->GetFieldIndex(i) - inobject;
|
| + if (target_index < 0) target_index += total_size;
|
| + Handle<Object> box = isolate->factory()->NewHeapNumber(0);
|
| + array->set(target_index, *box);
|
| + }
|
| + }
|
| +
|
| // From here on we cannot fail and we shouldn't GC anymore.
|
| DisallowHeapAllocation no_allocation;
|
|
|
| @@ -2552,7 +2540,6 @@ Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map,
|
|
|
|
|
| void Map::DeprecateTransitionTree() {
|
| - if (!FLAG_track_fields) return;
|
| if (is_deprecated()) return;
|
| if (HasTransitionArray()) {
|
| TransitionArray* transitions = this->transitions();
|
| @@ -2633,6 +2620,8 @@ Map* Map::FindUpdatedMap(int verbatim,
|
| current->instance_descriptors()->GetValue(i)) {
|
| return NULL;
|
| }
|
| + } else if (target_details.type() == CALLBACKS) {
|
| + return NULL;
|
| }
|
| }
|
|
|
| @@ -2854,7 +2843,7 @@ Handle<Object> JSObject::SetPropertyWithInterceptor(
|
| Handle<Name> name,
|
| Handle<Object> value,
|
| PropertyAttributes attributes,
|
| - StrictModeFlag strict_mode) {
|
| + StrictMode strict_mode) {
|
| // TODO(rossberg): Support symbols in the API.
|
| if (name->IsSymbol()) return value;
|
| Isolate* isolate = object->GetIsolate();
|
| @@ -2886,7 +2875,7 @@ Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object,
|
| Handle<Name> name,
|
| Handle<Object> value,
|
| PropertyAttributes attributes,
|
| - StrictModeFlag strict_mode,
|
| + StrictMode strict_mode,
|
| StoreFromKeyed store_mode) {
|
| LookupResult result(object->GetIsolate());
|
| object->LocalLookup(*name, &result, true);
|
| @@ -2903,7 +2892,7 @@ Handle<Object> JSObject::SetPropertyWithCallback(Handle<JSObject> object,
|
| Handle<Name> name,
|
| Handle<Object> value,
|
| Handle<JSObject> holder,
|
| - StrictModeFlag strict_mode) {
|
| + StrictMode strict_mode) {
|
| Isolate* isolate = object->GetIsolate();
|
|
|
| // We should never get here to initialize a const with the hole
|
| @@ -2962,9 +2951,7 @@ Handle<Object> JSObject::SetPropertyWithCallback(Handle<JSObject> object,
|
| return SetPropertyWithDefinedSetter(
|
| object, Handle<JSReceiver>::cast(setter), value);
|
| } else {
|
| - if (strict_mode == kNonStrictMode) {
|
| - return value;
|
| - }
|
| + if (strict_mode == SLOPPY) return value;
|
| Handle<Object> args[2] = { name, holder };
|
| Handle<Object> error =
|
| isolate->factory()->NewTypeError("no_setter_in_callback",
|
| @@ -3015,7 +3002,7 @@ Handle<Object> JSObject::SetElementWithCallbackSetterInPrototypes(
|
| uint32_t index,
|
| Handle<Object> value,
|
| bool* found,
|
| - StrictModeFlag strict_mode) {
|
| + StrictMode strict_mode) {
|
| Isolate *isolate = object->GetIsolate();
|
| for (Handle<Object> proto = handle(object->GetPrototype(), isolate);
|
| !proto->IsNull();
|
| @@ -3055,7 +3042,7 @@ Handle<Object> JSObject::SetPropertyViaPrototypes(Handle<JSObject> object,
|
| Handle<Name> name,
|
| Handle<Object> value,
|
| PropertyAttributes attributes,
|
| - StrictModeFlag strict_mode,
|
| + StrictMode strict_mode,
|
| bool* done) {
|
| Isolate* isolate = object->GetIsolate();
|
|
|
| @@ -3073,14 +3060,12 @@ Handle<Object> JSObject::SetPropertyViaPrototypes(Handle<JSObject> object,
|
| *done = result.IsReadOnly();
|
| break;
|
| case INTERCEPTOR: {
|
| - PropertyAttributes attr =
|
| - result.holder()->GetPropertyAttributeWithInterceptor(
|
| - *object, *name, true);
|
| + PropertyAttributes attr = GetPropertyAttributeWithInterceptor(
|
| + handle(result.holder()), object, name, true);
|
| *done = !!(attr & READ_ONLY);
|
| break;
|
| }
|
| case CALLBACKS: {
|
| - if (!FLAG_es5_readonly && result.IsReadOnly()) break;
|
| *done = true;
|
| Handle<Object> callback_object(result.GetCallbackObject(), isolate);
|
| return SetPropertyWithCallback(object, callback_object, name, value,
|
| @@ -3099,9 +3084,8 @@ Handle<Object> JSObject::SetPropertyViaPrototypes(Handle<JSObject> object,
|
| }
|
|
|
| // If we get here with *done true, we have encountered a read-only property.
|
| - if (!FLAG_es5_readonly) *done = false;
|
| if (*done) {
|
| - if (strict_mode == kNonStrictMode) return value;
|
| + if (strict_mode == SLOPPY) return value;
|
| Handle<Object> args[] = { name, object };
|
| Handle<Object> error = isolate->factory()->NewTypeError(
|
| "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
|
| @@ -3390,6 +3374,7 @@ MaybeObject* Map::AsElementsKind(ElementsKind kind) {
|
|
|
|
|
| void JSObject::LocalLookupRealNamedProperty(Name* name, LookupResult* result) {
|
| + DisallowHeapAllocation no_gc;
|
| if (IsJSGlobalProxy()) {
|
| Object* proto = GetPrototype();
|
| if (proto->IsNull()) return result->NotFound();
|
| @@ -3469,7 +3454,7 @@ Handle<Object> JSObject::SetPropertyWithFailedAccessCheck(
|
| Handle<Name> name,
|
| Handle<Object> value,
|
| bool check_prototype,
|
| - StrictModeFlag strict_mode) {
|
| + StrictMode strict_mode) {
|
| if (check_prototype && !result->IsProperty()) {
|
| object->LookupRealNamedPropertyInPrototypes(*name, result);
|
| }
|
| @@ -3525,7 +3510,7 @@ Handle<Object> JSObject::SetPropertyWithFailedAccessCheck(
|
| }
|
|
|
| Isolate* isolate = object->GetIsolate();
|
| - isolate->ReportFailedAccessCheck(*object, v8::ACCESS_SET);
|
| + isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_SET);
|
| RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| return value;
|
| }
|
| @@ -3536,7 +3521,7 @@ Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object,
|
| Handle<Name> key,
|
| Handle<Object> value,
|
| PropertyAttributes attributes,
|
| - StrictModeFlag strict_mode,
|
| + StrictMode strict_mode,
|
| StoreFromKeyed store_mode) {
|
| if (result->IsHandler()) {
|
| return JSProxy::SetPropertyWithHandler(handle(result->proxy()),
|
| @@ -3568,7 +3553,7 @@ Handle<Object> JSProxy::SetPropertyWithHandler(Handle<JSProxy> proxy,
|
| Handle<Name> name,
|
| Handle<Object> value,
|
| PropertyAttributes attributes,
|
| - StrictModeFlag strict_mode) {
|
| + StrictMode strict_mode) {
|
| Isolate* isolate = proxy->GetIsolate();
|
|
|
| // TODO(rossberg): adjust once there is a story for symbols vs proxies.
|
| @@ -3588,7 +3573,7 @@ Handle<Object> JSProxy::SetPropertyViaPrototypesWithHandler(
|
| Handle<Name> name,
|
| Handle<Object> value,
|
| PropertyAttributes attributes,
|
| - StrictModeFlag strict_mode,
|
| + StrictMode strict_mode,
|
| bool* done) {
|
| Isolate* isolate = proxy->GetIsolate();
|
| Handle<Object> handler(proxy->handler(), isolate); // Trap might morph proxy.
|
| @@ -3656,7 +3641,7 @@ Handle<Object> JSProxy::SetPropertyViaPrototypesWithHandler(
|
| ASSERT(writable->IsTrue() || writable->IsFalse());
|
| *done = writable->IsFalse();
|
| if (!*done) return isolate->factory()->the_hole_value();
|
| - if (strict_mode == kNonStrictMode) return value;
|
| + if (strict_mode == SLOPPY) return value;
|
| Handle<Object> args[] = { name, receiver };
|
| Handle<Object> error = isolate->factory()->NewTypeError(
|
| "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
|
| @@ -3675,7 +3660,7 @@ Handle<Object> JSProxy::SetPropertyViaPrototypesWithHandler(
|
| receiver, Handle<JSReceiver>::cast(setter), value);
|
| }
|
|
|
| - if (strict_mode == kNonStrictMode) return value;
|
| + if (strict_mode == SLOPPY) return value;
|
| Handle<Object> args2[] = { name, proxy };
|
| Handle<Object> error = isolate->factory()->NewTypeError(
|
| "no_setter_in_callback", HandleVector(args2, ARRAY_SIZE(args2)));
|
| @@ -3719,21 +3704,18 @@ Handle<Object> JSProxy::DeleteElementWithHandler(
|
| }
|
|
|
|
|
| -MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler(
|
| - JSReceiver* receiver_raw,
|
| - Name* name_raw) {
|
| - Isolate* isolate = GetIsolate();
|
| +PropertyAttributes JSProxy::GetPropertyAttributeWithHandler(
|
| + Handle<JSProxy> proxy,
|
| + Handle<JSReceiver> receiver,
|
| + Handle<Name> name) {
|
| + Isolate* isolate = proxy->GetIsolate();
|
| HandleScope scope(isolate);
|
| - Handle<JSProxy> proxy(this);
|
| - Handle<Object> handler(this->handler(), isolate); // Trap might morph proxy.
|
| - Handle<JSReceiver> receiver(receiver_raw);
|
| - Handle<Object> name(name_raw, isolate);
|
|
|
| // TODO(rossberg): adjust once there is a story for symbols vs proxies.
|
| if (name->IsSymbol()) return ABSENT;
|
|
|
| Handle<Object> args[] = { name };
|
| - Handle<Object> result = CallTrap(
|
| + Handle<Object> result = proxy->CallTrap(
|
| "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args);
|
| if (isolate->has_pending_exception()) return NONE;
|
|
|
| @@ -3768,6 +3750,7 @@ MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler(
|
| }
|
|
|
| if (configurable->IsFalse()) {
|
| + Handle<Object> handler(proxy->handler(), isolate);
|
| Handle<String> trap = isolate->factory()->InternalizeOneByteString(
|
| STATIC_ASCII_VECTOR("getPropertyDescriptor"));
|
| Handle<Object> args[] = { handler, trap, name };
|
| @@ -3785,15 +3768,13 @@ MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler(
|
| }
|
|
|
|
|
| -MUST_USE_RESULT PropertyAttributes JSProxy::GetElementAttributeWithHandler(
|
| - JSReceiver* receiver_raw,
|
| +PropertyAttributes JSProxy::GetElementAttributeWithHandler(
|
| + Handle<JSProxy> proxy,
|
| + Handle<JSReceiver> receiver,
|
| uint32_t index) {
|
| - Isolate* isolate = GetIsolate();
|
| - HandleScope scope(isolate);
|
| - Handle<JSProxy> proxy(this);
|
| - Handle<JSReceiver> receiver(receiver_raw);
|
| + Isolate* isolate = proxy->GetIsolate();
|
| Handle<String> name = isolate->factory()->Uint32ToString(index);
|
| - return proxy->GetPropertyAttributeWithHandler(*receiver, *name);
|
| + return GetPropertyAttributeWithHandler(proxy, receiver, name);
|
| }
|
|
|
|
|
| @@ -3869,16 +3850,7 @@ void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) {
|
| }
|
| map = MapAsElementsKind(map, to_kind);
|
| }
|
| - int total_size =
|
| - map->NumberOfOwnDescriptors() + map->unused_property_fields();
|
| - int out_of_object = total_size - map->inobject_properties();
|
| - if (out_of_object != object->properties()->length()) {
|
| - Isolate* isolate = object->GetIsolate();
|
| - Handle<FixedArray> new_properties = isolate->factory()->CopySizeFixedArray(
|
| - handle(object->properties()), out_of_object);
|
| - object->set_properties(*new_properties);
|
| - }
|
| - object->set_map(*map);
|
| + JSObject::MigrateToMap(object, map);
|
| }
|
|
|
|
|
| @@ -3925,7 +3897,7 @@ Handle<Object> JSObject::SetPropertyUsingTransition(
|
| // of the map. If we get a fast copy of the map, all field representations
|
| // will be tagged since the transition is omitted.
|
| return JSObject::AddProperty(
|
| - object, name, value, attributes, kNonStrictMode,
|
| + object, name, value, attributes, SLOPPY,
|
| JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED,
|
| JSReceiver::OMIT_EXTENSIBILITY_CHECK,
|
| JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION);
|
| @@ -3934,29 +3906,31 @@ Handle<Object> JSObject::SetPropertyUsingTransition(
|
| // Keep the target CONSTANT if the same value is stored.
|
| // TODO(verwaest): Also support keeping the placeholder
|
| // (value->IsUninitialized) as constant.
|
| - if (details.type() == CONSTANT &&
|
| - descriptors->GetValue(descriptor) == *value) {
|
| - object->set_map(*transition_map);
|
| - return value;
|
| - }
|
| -
|
| - Representation representation = details.representation();
|
| -
|
| - if (!value->FitsRepresentation(representation) ||
|
| - details.type() == CONSTANT) {
|
| + if (!value->FitsRepresentation(details.representation()) ||
|
| + (details.type() == CONSTANT &&
|
| + descriptors->GetValue(descriptor) != *value)) {
|
| transition_map = Map::GeneralizeRepresentation(transition_map,
|
| descriptor, value->OptimalRepresentation(), FORCE_FIELD);
|
| - Object* back = transition_map->GetBackPointer();
|
| - if (back->IsMap()) {
|
| - MigrateToMap(object, handle(Map::cast(back)));
|
| - }
|
| - descriptors = transition_map->instance_descriptors();
|
| - representation = descriptors->GetDetails(descriptor).representation();
|
| }
|
|
|
| + JSObject::MigrateToMap(object, transition_map);
|
| +
|
| + // Reload.
|
| + descriptors = transition_map->instance_descriptors();
|
| + details = descriptors->GetDetails(descriptor);
|
| +
|
| + if (details.type() != FIELD) return value;
|
| +
|
| int field_index = descriptors->GetFieldIndex(descriptor);
|
| - AddFastPropertyUsingMap(
|
| - object, transition_map, name, value, field_index, representation);
|
| + if (details.representation().IsDouble()) {
|
| + // Nothing more to be done.
|
| + if (value->IsUninitialized()) return value;
|
| + HeapNumber* box = HeapNumber::cast(object->RawFastPropertyAt(field_index));
|
| + box->set_value(value->Number());
|
| + } else {
|
| + object->FastPropertyAtPut(field_index, *value);
|
| + }
|
| +
|
| return value;
|
| }
|
|
|
| @@ -3976,7 +3950,7 @@ static void SetPropertyToField(LookupResult* lookup,
|
| representation = desc->GetDetails(descriptor).representation();
|
| }
|
|
|
| - if (FLAG_track_double_fields && representation.IsDouble()) {
|
| + if (representation.IsDouble()) {
|
| HeapNumber* storage = HeapNumber::cast(lookup->holder()->RawFastPropertyAt(
|
| lookup->GetFieldIndex().field_index()));
|
| storage->set_value(value->Number());
|
| @@ -4037,7 +4011,7 @@ Handle<Object> JSObject::SetPropertyForResult(Handle<JSObject> object,
|
| Handle<Name> name,
|
| Handle<Object> value,
|
| PropertyAttributes attributes,
|
| - StrictModeFlag strict_mode,
|
| + StrictMode strict_mode,
|
| StoreFromKeyed store_mode) {
|
| Isolate* isolate = object->GetIsolate();
|
|
|
| @@ -4055,7 +4029,7 @@ Handle<Object> JSObject::SetPropertyForResult(Handle<JSObject> object,
|
|
|
| // Check access rights if needed.
|
| if (object->IsAccessCheckNeeded()) {
|
| - if (!isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) {
|
| + if (!isolate->MayNamedAccessWrapper(object, name, v8::ACCESS_SET)) {
|
| return SetPropertyWithFailedAccessCheck(object, lookup, name, value,
|
| true, strict_mode);
|
| }
|
| @@ -4086,7 +4060,7 @@ Handle<Object> JSObject::SetPropertyForResult(Handle<JSObject> object,
|
| }
|
|
|
| if (lookup->IsProperty() && lookup->IsReadOnly()) {
|
| - if (strict_mode == kStrictMode) {
|
| + if (strict_mode == STRICT) {
|
| Handle<Object> args[] = { name, object };
|
| Handle<Object> error = isolate->factory()->NewTypeError(
|
| "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
|
| @@ -4098,8 +4072,7 @@ Handle<Object> JSObject::SetPropertyForResult(Handle<JSObject> object,
|
| }
|
|
|
| Handle<Object> old_value = isolate->factory()->the_hole_value();
|
| - bool is_observed = FLAG_harmony_observation &&
|
| - object->map()->is_observed() &&
|
| + bool is_observed = object->map()->is_observed() &&
|
| *name != isolate->heap()->hidden_string();
|
| if (is_observed && lookup->IsDataProperty()) {
|
| old_value = Object::GetProperty(object, name);
|
| @@ -4190,9 +4163,9 @@ Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes(
|
|
|
| // Check access rights if needed.
|
| if (object->IsAccessCheckNeeded()) {
|
| - if (!isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) {
|
| + if (!isolate->MayNamedAccessWrapper(object, name, v8::ACCESS_SET)) {
|
| return SetPropertyWithFailedAccessCheck(object, &lookup, name, value,
|
| - false, kNonStrictMode);
|
| + false, SLOPPY);
|
| }
|
| }
|
|
|
| @@ -4215,14 +4188,13 @@ Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes(
|
| TransitionFlag flag = lookup.IsFound()
|
| ? OMIT_TRANSITION : INSERT_TRANSITION;
|
| // Neither properties nor transitions found.
|
| - return AddProperty(object, name, value, attributes, kNonStrictMode,
|
| + return AddProperty(object, name, value, attributes, SLOPPY,
|
| MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode, flag);
|
| }
|
|
|
| Handle<Object> old_value = isolate->factory()->the_hole_value();
|
| PropertyAttributes old_attributes = ABSENT;
|
| - bool is_observed = FLAG_harmony_observation &&
|
| - object->map()->is_observed() &&
|
| + bool is_observed = object->map()->is_observed() &&
|
| *name != isolate->heap()->hidden_string();
|
| if (is_observed && lookup.IsProperty()) {
|
| if (lookup.IsDataProperty()) old_value =
|
| @@ -4287,20 +4259,22 @@ Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes(
|
|
|
|
|
| PropertyAttributes JSObject::GetPropertyAttributePostInterceptor(
|
| - JSObject* receiver,
|
| - Name* name,
|
| - bool continue_search) {
|
| + Handle<JSObject> object,
|
| + Handle<JSObject> receiver,
|
| + Handle<Name> name,
|
| + bool continue_search) {
|
| // Check local property, ignore interceptor.
|
| - LookupResult result(GetIsolate());
|
| - LocalLookupRealNamedProperty(name, &result);
|
| + Isolate* isolate = object->GetIsolate();
|
| + LookupResult result(isolate);
|
| + object->LocalLookupRealNamedProperty(*name, &result);
|
| if (result.IsFound()) return result.GetAttributes();
|
|
|
| if (continue_search) {
|
| // Continue searching via the prototype chain.
|
| - Object* pt = GetPrototype();
|
| - if (!pt->IsNull()) {
|
| - return JSObject::cast(pt)->
|
| - GetPropertyAttributeWithReceiver(receiver, name);
|
| + Handle<Object> proto(object->GetPrototype(), isolate);
|
| + if (!proto->IsNull()) {
|
| + return JSReceiver::GetPropertyAttributeWithReceiver(
|
| + Handle<JSObject>::cast(proto), receiver, name);
|
| }
|
| }
|
| return ABSENT;
|
| @@ -4308,31 +4282,30 @@ PropertyAttributes JSObject::GetPropertyAttributePostInterceptor(
|
|
|
|
|
| PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor(
|
| - JSObject* receiver,
|
| - Name* name,
|
| - bool continue_search) {
|
| + Handle<JSObject> object,
|
| + Handle<JSObject> receiver,
|
| + Handle<Name> name,
|
| + bool continue_search) {
|
| // TODO(rossberg): Support symbols in the API.
|
| if (name->IsSymbol()) return ABSENT;
|
|
|
| - Isolate* isolate = GetIsolate();
|
| + Isolate* isolate = object->GetIsolate();
|
| HandleScope scope(isolate);
|
|
|
| // Make sure that the top context does not change when doing
|
| // callbacks or interceptor calls.
|
| AssertNoContextChange ncc(isolate);
|
|
|
| - Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
|
| - Handle<JSObject> receiver_handle(receiver);
|
| - Handle<JSObject> holder_handle(this);
|
| - Handle<String> name_handle(String::cast(name));
|
| - PropertyCallbackArguments args(isolate, interceptor->data(), receiver, this);
|
| + Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor());
|
| + PropertyCallbackArguments args(
|
| + isolate, interceptor->data(), *receiver, *object);
|
| if (!interceptor->query()->IsUndefined()) {
|
| v8::NamedPropertyQueryCallback query =
|
| v8::ToCData<v8::NamedPropertyQueryCallback>(interceptor->query());
|
| LOG(isolate,
|
| - ApiNamedPropertyAccess("interceptor-named-has", *holder_handle, name));
|
| + ApiNamedPropertyAccess("interceptor-named-has", *object, *name));
|
| v8::Handle<v8::Integer> result =
|
| - args.Call(query, v8::Utils::ToLocal(name_handle));
|
| + args.Call(query, v8::Utils::ToLocal(Handle<String>::cast(name)));
|
| if (!result.IsEmpty()) {
|
| ASSERT(result->IsInt32());
|
| return static_cast<PropertyAttributes>(result->Int32Value());
|
| @@ -4341,44 +4314,45 @@ PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor(
|
| v8::NamedPropertyGetterCallback getter =
|
| v8::ToCData<v8::NamedPropertyGetterCallback>(interceptor->getter());
|
| LOG(isolate,
|
| - ApiNamedPropertyAccess("interceptor-named-get-has", this, name));
|
| + ApiNamedPropertyAccess("interceptor-named-get-has", *object, *name));
|
| v8::Handle<v8::Value> result =
|
| - args.Call(getter, v8::Utils::ToLocal(name_handle));
|
| + args.Call(getter, v8::Utils::ToLocal(Handle<String>::cast(name)));
|
| if (!result.IsEmpty()) return DONT_ENUM;
|
| }
|
| - return holder_handle->GetPropertyAttributePostInterceptor(*receiver_handle,
|
| - *name_handle,
|
| - continue_search);
|
| + return GetPropertyAttributePostInterceptor(
|
| + object, receiver, name, continue_search);
|
| }
|
|
|
|
|
| PropertyAttributes JSReceiver::GetPropertyAttributeWithReceiver(
|
| - JSReceiver* receiver,
|
| - Name* key) {
|
| + Handle<JSReceiver> object,
|
| + Handle<JSReceiver> receiver,
|
| + Handle<Name> key) {
|
| uint32_t index = 0;
|
| - if (IsJSObject() && key->AsArrayIndex(&index)) {
|
| - return JSObject::cast(this)->GetElementAttributeWithReceiver(
|
| - receiver, index, true);
|
| + if (object->IsJSObject() && key->AsArrayIndex(&index)) {
|
| + return JSObject::GetElementAttributeWithReceiver(
|
| + Handle<JSObject>::cast(object), receiver, index, true);
|
| }
|
| // Named property.
|
| - LookupResult lookup(GetIsolate());
|
| - Lookup(key, &lookup);
|
| - return GetPropertyAttributeForResult(receiver, &lookup, key, true);
|
| + LookupResult lookup(object->GetIsolate());
|
| + object->Lookup(*key, &lookup);
|
| + return GetPropertyAttributeForResult(object, receiver, &lookup, key, true);
|
| }
|
|
|
|
|
| PropertyAttributes JSReceiver::GetPropertyAttributeForResult(
|
| - JSReceiver* receiver,
|
| + Handle<JSReceiver> object,
|
| + Handle<JSReceiver> receiver,
|
| LookupResult* lookup,
|
| - Name* name,
|
| + Handle<Name> name,
|
| bool continue_search) {
|
| // Check access rights if needed.
|
| - if (IsAccessCheckNeeded()) {
|
| - JSObject* this_obj = JSObject::cast(this);
|
| - Heap* heap = GetHeap();
|
| - if (!heap->isolate()->MayNamedAccess(this_obj, name, v8::ACCESS_HAS)) {
|
| - return this_obj->GetPropertyAttributeWithFailedAccessCheck(
|
| - receiver, lookup, name, continue_search);
|
| + if (object->IsAccessCheckNeeded()) {
|
| + Heap* heap = object->GetHeap();
|
| + Handle<JSObject> obj = Handle<JSObject>::cast(object);
|
| + if (!heap->isolate()->MayNamedAccessWrapper(obj, name, v8::ACCESS_HAS)) {
|
| + return JSObject::GetPropertyAttributeWithFailedAccessCheck(
|
| + obj, lookup, name, continue_search);
|
| }
|
| }
|
| if (lookup->IsFound()) {
|
| @@ -4389,12 +4363,15 @@ PropertyAttributes JSReceiver::GetPropertyAttributeForResult(
|
| case CALLBACKS:
|
| return lookup->GetAttributes();
|
| case HANDLER: {
|
| - return JSProxy::cast(lookup->proxy())->GetPropertyAttributeWithHandler(
|
| - receiver, name);
|
| + return JSProxy::GetPropertyAttributeWithHandler(
|
| + handle(lookup->proxy()), receiver, name);
|
| }
|
| case INTERCEPTOR:
|
| - return lookup->holder()->GetPropertyAttributeWithInterceptor(
|
| - JSObject::cast(receiver), name, continue_search);
|
| + return JSObject::GetPropertyAttributeWithInterceptor(
|
| + handle(lookup->holder()),
|
| + Handle<JSObject>::cast(receiver),
|
| + name,
|
| + continue_search);
|
| case TRANSITION:
|
| case NONEXISTENT:
|
| UNREACHABLE();
|
| @@ -4404,67 +4381,74 @@ PropertyAttributes JSReceiver::GetPropertyAttributeForResult(
|
| }
|
|
|
|
|
| -PropertyAttributes JSReceiver::GetLocalPropertyAttribute(Name* name) {
|
| +PropertyAttributes JSReceiver::GetLocalPropertyAttribute(
|
| + Handle<JSReceiver> object, Handle<Name> name) {
|
| // Check whether the name is an array index.
|
| uint32_t index = 0;
|
| - if (IsJSObject() && name->AsArrayIndex(&index)) {
|
| - return GetLocalElementAttribute(index);
|
| + if (object->IsJSObject() && name->AsArrayIndex(&index)) {
|
| + return GetLocalElementAttribute(object, index);
|
| }
|
| // Named property.
|
| - LookupResult lookup(GetIsolate());
|
| - LocalLookup(name, &lookup, true);
|
| - return GetPropertyAttributeForResult(this, &lookup, name, false);
|
| + LookupResult lookup(object->GetIsolate());
|
| + object->LocalLookup(*name, &lookup, true);
|
| + return GetPropertyAttributeForResult(object, object, &lookup, name, false);
|
| }
|
|
|
|
|
| PropertyAttributes JSObject::GetElementAttributeWithReceiver(
|
| - JSReceiver* receiver, uint32_t index, bool continue_search) {
|
| - Isolate* isolate = GetIsolate();
|
| + Handle<JSObject> object,
|
| + Handle<JSReceiver> receiver,
|
| + uint32_t index,
|
| + bool continue_search) {
|
| + Isolate* isolate = object->GetIsolate();
|
|
|
| // Check access rights if needed.
|
| - if (IsAccessCheckNeeded()) {
|
| - if (!isolate->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
|
| - isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
|
| + if (object->IsAccessCheckNeeded()) {
|
| + if (!isolate->MayIndexedAccessWrapper(object, index, v8::ACCESS_HAS)) {
|
| + isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_HAS);
|
| return ABSENT;
|
| }
|
| }
|
|
|
| - if (IsJSGlobalProxy()) {
|
| - Object* proto = GetPrototype();
|
| + if (object->IsJSGlobalProxy()) {
|
| + Handle<Object> proto(object->GetPrototype(), isolate);
|
| if (proto->IsNull()) return ABSENT;
|
| ASSERT(proto->IsJSGlobalObject());
|
| - return JSObject::cast(proto)->GetElementAttributeWithReceiver(
|
| - receiver, index, continue_search);
|
| + return JSObject::GetElementAttributeWithReceiver(
|
| + Handle<JSObject>::cast(proto), receiver, index, continue_search);
|
| }
|
|
|
| // Check for lookup interceptor except when bootstrapping.
|
| - if (HasIndexedInterceptor() && !isolate->bootstrapper()->IsActive()) {
|
| - return GetElementAttributeWithInterceptor(receiver, index, continue_search);
|
| + if (object->HasIndexedInterceptor() && !isolate->bootstrapper()->IsActive()) {
|
| + return JSObject::GetElementAttributeWithInterceptor(
|
| + object, receiver, index, continue_search);
|
| }
|
|
|
| return GetElementAttributeWithoutInterceptor(
|
| - receiver, index, continue_search);
|
| + object, receiver, index, continue_search);
|
| }
|
|
|
|
|
| PropertyAttributes JSObject::GetElementAttributeWithInterceptor(
|
| - JSReceiver* receiver, uint32_t index, bool continue_search) {
|
| - Isolate* isolate = GetIsolate();
|
| + Handle<JSObject> object,
|
| + Handle<JSReceiver> receiver,
|
| + uint32_t index,
|
| + bool continue_search) {
|
| + Isolate* isolate = object->GetIsolate();
|
| HandleScope scope(isolate);
|
|
|
| // Make sure that the top context does not change when doing
|
| // callbacks or interceptor calls.
|
| AssertNoContextChange ncc(isolate);
|
|
|
| - Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
|
| - Handle<JSReceiver> hreceiver(receiver);
|
| - Handle<JSObject> holder(this);
|
| - PropertyCallbackArguments args(isolate, interceptor->data(), receiver, this);
|
| + Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor());
|
| + PropertyCallbackArguments args(
|
| + isolate, interceptor->data(), *receiver, *object);
|
| if (!interceptor->query()->IsUndefined()) {
|
| v8::IndexedPropertyQueryCallback query =
|
| v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query());
|
| LOG(isolate,
|
| - ApiIndexedPropertyAccess("interceptor-indexed-has", this, index));
|
| + ApiIndexedPropertyAccess("interceptor-indexed-has", *object, index));
|
| v8::Handle<v8::Integer> result = args.Call(query, index);
|
| if (!result.IsEmpty())
|
| return static_cast<PropertyAttributes>(result->Int32Value());
|
| @@ -4472,37 +4456,42 @@ PropertyAttributes JSObject::GetElementAttributeWithInterceptor(
|
| v8::IndexedPropertyGetterCallback getter =
|
| v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
|
| LOG(isolate,
|
| - ApiIndexedPropertyAccess("interceptor-indexed-get-has", this, index));
|
| + ApiIndexedPropertyAccess(
|
| + "interceptor-indexed-get-has", *object, index));
|
| v8::Handle<v8::Value> result = args.Call(getter, index);
|
| if (!result.IsEmpty()) return NONE;
|
| }
|
|
|
| - return holder->GetElementAttributeWithoutInterceptor(
|
| - *hreceiver, index, continue_search);
|
| + return GetElementAttributeWithoutInterceptor(
|
| + object, receiver, index, continue_search);
|
| }
|
|
|
|
|
| PropertyAttributes JSObject::GetElementAttributeWithoutInterceptor(
|
| - JSReceiver* receiver, uint32_t index, bool continue_search) {
|
| - PropertyAttributes attr = GetElementsAccessor()->GetAttributes(
|
| - receiver, this, index);
|
| + Handle<JSObject> object,
|
| + Handle<JSReceiver> receiver,
|
| + uint32_t index,
|
| + bool continue_search) {
|
| + PropertyAttributes attr = object->GetElementsAccessor()->GetAttributes(
|
| + *receiver, *object, index);
|
| if (attr != ABSENT) return attr;
|
|
|
| // Handle [] on String objects.
|
| - if (IsStringObjectWithCharacterAt(index)) {
|
| + if (object->IsStringObjectWithCharacterAt(index)) {
|
| return static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
|
| }
|
|
|
| if (!continue_search) return ABSENT;
|
|
|
| - Object* pt = GetPrototype();
|
| - if (pt->IsJSProxy()) {
|
| + Handle<Object> proto(object->GetPrototype(), object->GetIsolate());
|
| + if (proto->IsJSProxy()) {
|
| // We need to follow the spec and simulate a call to [[GetOwnProperty]].
|
| - return JSProxy::cast(pt)->GetElementAttributeWithHandler(receiver, index);
|
| + return JSProxy::GetElementAttributeWithHandler(
|
| + Handle<JSProxy>::cast(proto), receiver, index);
|
| }
|
| - if (pt->IsNull()) return ABSENT;
|
| - return JSObject::cast(pt)->GetElementAttributeWithReceiver(
|
| - receiver, index, true);
|
| + if (proto->IsNull()) return ABSENT;
|
| + return GetElementAttributeWithReceiver(
|
| + Handle<JSObject>::cast(proto), receiver, index, true);
|
| }
|
|
|
|
|
| @@ -4745,7 +4734,7 @@ MaybeObject* JSObject::NormalizeElements() {
|
| FixedArrayBase* array = FixedArrayBase::cast(elements());
|
| Map* old_map = array->map();
|
| bool is_arguments =
|
| - (old_map == old_map->GetHeap()->non_strict_arguments_elements_map());
|
| + (old_map == old_map->GetHeap()->sloppy_arguments_elements_map());
|
| if (is_arguments) {
|
| array = FixedArrayBase::cast(FixedArray::cast(array)->get(1));
|
| }
|
| @@ -4780,6 +4769,7 @@ MaybeObject* JSObject::NormalizeElements() {
|
| MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(),
|
| DICTIONARY_ELEMENTS);
|
| if (!maybe->To(&new_map)) return maybe;
|
| + // TODO(verwaest): Replace by MigrateToMap.
|
| set_map(new_map);
|
| set_elements(dictionary);
|
| }
|
| @@ -4960,10 +4950,10 @@ void JSObject::DeleteHiddenProperty(Handle<JSObject> object, Handle<Name> key) {
|
| }
|
|
|
|
|
| -bool JSObject::HasHiddenProperties() {
|
| - return GetPropertyAttributePostInterceptor(this,
|
| - GetHeap()->hidden_string(),
|
| - false) != ABSENT;
|
| +bool JSObject::HasHiddenProperties(Handle<JSObject> object) {
|
| + Handle<Name> hidden = object->GetIsolate()->factory()->hidden_string();
|
| + return GetPropertyAttributePostInterceptor(
|
| + object, object, hidden, false) != ABSENT;
|
| }
|
|
|
|
|
| @@ -5044,7 +5034,7 @@ Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object,
|
|
|
| // We can store the identity hash inline iff there is no backing store
|
| // for hidden properties yet.
|
| - ASSERT(object->HasHiddenProperties() != value->IsSmi());
|
| + ASSERT(JSObject::HasHiddenProperties(object) != value->IsSmi());
|
| if (object->HasFastProperties()) {
|
| // If the object has fast properties, check whether the first slot
|
| // in the descriptor array matches the hidden string. Since the
|
| @@ -5175,8 +5165,8 @@ Handle<Object> JSObject::DeleteElement(Handle<JSObject> object,
|
|
|
| // Check access rights if needed.
|
| if (object->IsAccessCheckNeeded() &&
|
| - !isolate->MayIndexedAccess(*object, index, v8::ACCESS_DELETE)) {
|
| - isolate->ReportFailedAccessCheck(*object, v8::ACCESS_DELETE);
|
| + !isolate->MayIndexedAccessWrapper(object, index, v8::ACCESS_DELETE)) {
|
| + isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_DELETE);
|
| RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| return factory->false_value();
|
| }
|
| @@ -5204,7 +5194,7 @@ Handle<Object> JSObject::DeleteElement(Handle<JSObject> object,
|
|
|
| Handle<Object> old_value;
|
| bool should_enqueue_change_record = false;
|
| - if (FLAG_harmony_observation && object->map()->is_observed()) {
|
| + if (object->map()->is_observed()) {
|
| should_enqueue_change_record = HasLocalElement(object, index);
|
| if (should_enqueue_change_record) {
|
| old_value = object->GetLocalElementAccessorPair(index) != NULL
|
| @@ -5239,8 +5229,8 @@ Handle<Object> JSObject::DeleteProperty(Handle<JSObject> object,
|
|
|
| // Check access rights if needed.
|
| if (object->IsAccessCheckNeeded() &&
|
| - !isolate->MayNamedAccess(*object, *name, v8::ACCESS_DELETE)) {
|
| - isolate->ReportFailedAccessCheck(*object, v8::ACCESS_DELETE);
|
| + !isolate->MayNamedAccessWrapper(object, name, v8::ACCESS_DELETE)) {
|
| + isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_DELETE);
|
| RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| return isolate->factory()->false_value();
|
| }
|
| @@ -5275,8 +5265,7 @@ Handle<Object> JSObject::DeleteProperty(Handle<JSObject> object,
|
| }
|
|
|
| Handle<Object> old_value = isolate->factory()->the_hole_value();
|
| - bool is_observed = FLAG_harmony_observation &&
|
| - object->map()->is_observed() &&
|
| + bool is_observed = object->map()->is_observed() &&
|
| *name != isolate->heap()->hidden_string();
|
| if (is_observed && lookup.IsDataProperty()) {
|
| old_value = Object::GetProperty(object, name);
|
| @@ -5398,7 +5387,7 @@ bool JSObject::ReferencesObject(Object* obj) {
|
| if (ReferencesObjectFromElements(elements, kind, obj)) return true;
|
| break;
|
| }
|
| - case NON_STRICT_ARGUMENTS_ELEMENTS: {
|
| + case SLOPPY_ARGUMENTS_ELEMENTS: {
|
| FixedArray* parameter_map = FixedArray::cast(elements());
|
| // Check the mapped parameters.
|
| int length = parameter_map->length();
|
| @@ -5420,7 +5409,7 @@ bool JSObject::ReferencesObject(Object* obj) {
|
| // Get the constructor function for arguments array.
|
| JSObject* arguments_boilerplate =
|
| heap->isolate()->context()->native_context()->
|
| - arguments_boilerplate();
|
| + sloppy_arguments_boilerplate();
|
| JSFunction* arguments_function =
|
| JSFunction::cast(arguments_boilerplate->map()->constructor());
|
|
|
| @@ -5470,10 +5459,10 @@ Handle<Object> JSObject::PreventExtensions(Handle<JSObject> object) {
|
| if (!object->map()->is_extensible()) return object;
|
|
|
| if (object->IsAccessCheckNeeded() &&
|
| - !isolate->MayNamedAccess(*object,
|
| - isolate->heap()->undefined_value(),
|
| - v8::ACCESS_KEYS)) {
|
| - isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS);
|
| + !isolate->MayNamedAccessWrapper(object,
|
| + isolate->factory()->undefined_value(),
|
| + v8::ACCESS_KEYS)) {
|
| + isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_KEYS);
|
| RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| return isolate->factory()->false_value();
|
| }
|
| @@ -5509,10 +5498,10 @@ Handle<Object> JSObject::PreventExtensions(Handle<JSObject> object) {
|
| Handle<Map> new_map = Map::Copy(handle(object->map()));
|
|
|
| new_map->set_is_extensible(false);
|
| - object->set_map(*new_map);
|
| + JSObject::MigrateToMap(object, new_map);
|
| ASSERT(!object->map()->is_extensible());
|
|
|
| - if (FLAG_harmony_observation && object->map()->is_observed()) {
|
| + if (object->map()->is_observed()) {
|
| EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(),
|
| isolate->factory()->the_hole_value());
|
| }
|
| @@ -5542,18 +5531,18 @@ static void FreezeDictionary(Dictionary* dictionary) {
|
|
|
|
|
| Handle<Object> JSObject::Freeze(Handle<JSObject> object) {
|
| - // Freezing non-strict arguments should be handled elsewhere.
|
| - ASSERT(!object->HasNonStrictArgumentsElements());
|
| + // Freezing sloppy arguments should be handled elsewhere.
|
| + ASSERT(!object->HasSloppyArgumentsElements());
|
| ASSERT(!object->map()->is_observed());
|
|
|
| if (object->map()->is_frozen()) return object;
|
|
|
| Isolate* isolate = object->GetIsolate();
|
| if (object->IsAccessCheckNeeded() &&
|
| - !isolate->MayNamedAccess(*object,
|
| - isolate->heap()->undefined_value(),
|
| - v8::ACCESS_KEYS)) {
|
| - isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS);
|
| + !isolate->MayNamedAccessWrapper(object,
|
| + isolate->factory()->undefined_value(),
|
| + v8::ACCESS_KEYS)) {
|
| + isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_KEYS);
|
| RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| return isolate->factory()->false_value();
|
| }
|
| @@ -5602,11 +5591,11 @@ Handle<Object> JSObject::Freeze(Handle<JSObject> object) {
|
| Handle<Map> old_map(object->map());
|
| old_map->LookupTransition(*object, isolate->heap()->frozen_symbol(), &result);
|
| if (result.IsTransition()) {
|
| - Map* transition_map = result.GetTransitionTarget();
|
| + Handle<Map> transition_map(result.GetTransitionTarget());
|
| ASSERT(transition_map->has_dictionary_elements());
|
| ASSERT(transition_map->is_frozen());
|
| ASSERT(!transition_map->is_extensible());
|
| - object->set_map(transition_map);
|
| + JSObject::MigrateToMap(object, transition_map);
|
| } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) {
|
| // Create a new descriptor array with fully-frozen properties
|
| int num_descriptors = old_map->NumberOfOwnDescriptors();
|
| @@ -5619,7 +5608,7 @@ Handle<Object> JSObject::Freeze(Handle<JSObject> object) {
|
| new_map->freeze();
|
| new_map->set_is_extensible(false);
|
| new_map->set_elements_kind(DICTIONARY_ELEMENTS);
|
| - object->set_map(*new_map);
|
| + JSObject::MigrateToMap(object, new_map);
|
| } else {
|
| // Slow path: need to normalize properties for safety
|
| NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
|
| @@ -5630,7 +5619,7 @@ Handle<Object> JSObject::Freeze(Handle<JSObject> object) {
|
| new_map->freeze();
|
| new_map->set_is_extensible(false);
|
| new_map->set_elements_kind(DICTIONARY_ELEMENTS);
|
| - object->set_map(*new_map);
|
| + JSObject::MigrateToMap(object, new_map);
|
|
|
| // Freeze dictionary-mode properties
|
| FreezeDictionary(object->property_dictionary());
|
| @@ -5674,7 +5663,7 @@ void JSObject::SetObserved(Handle<JSObject> object) {
|
| new_map = Map::Copy(handle(object->map()));
|
| new_map->set_is_observed();
|
| }
|
| - object->set_map(*new_map);
|
| + JSObject::MigrateToMap(object, new_map);
|
| }
|
|
|
|
|
| @@ -5795,7 +5784,7 @@ Handle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
|
| ASSERT(names->get(i)->IsString());
|
| Handle<String> key_string(String::cast(names->get(i)));
|
| PropertyAttributes attributes =
|
| - copy->GetLocalPropertyAttribute(*key_string);
|
| + JSReceiver::GetLocalPropertyAttribute(copy, key_string);
|
| // Only deep copy fields from the object literal expression.
|
| // In particular, don't try to copy the length attribute of
|
| // an array.
|
| @@ -5810,7 +5799,7 @@ Handle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
|
| if (copying) {
|
| // Creating object copy for literals. No strict mode needed.
|
| CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetProperty(
|
| - copy, key_string, result, NONE, kNonStrictMode));
|
| + copy, key_string, result, NONE, SLOPPY));
|
| }
|
| }
|
| }
|
| @@ -5869,7 +5858,7 @@ Handle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
|
| }
|
| break;
|
| }
|
| - case NON_STRICT_ARGUMENTS_ELEMENTS:
|
| + case SLOPPY_ARGUMENTS_ELEMENTS:
|
| UNIMPLEMENTED();
|
| break;
|
|
|
| @@ -5927,9 +5916,9 @@ bool JSReceiver::IsSimpleEnum() {
|
| JSObject* curr = JSObject::cast(o);
|
| int enum_length = curr->map()->EnumLength();
|
| if (enum_length == kInvalidEnumCacheSentinel) return false;
|
| + if (curr->IsAccessCheckNeeded()) return false;
|
| ASSERT(!curr->HasNamedInterceptor());
|
| ASSERT(!curr->HasIndexedInterceptor());
|
| - ASSERT(!curr->IsAccessCheckNeeded());
|
| if (curr->NumberOfEnumElements() > 0) return false;
|
| if (curr != this && enum_length != 0) return false;
|
| }
|
| @@ -6130,7 +6119,7 @@ void JSObject::DefineElementAccessor(Handle<JSObject> object,
|
| return;
|
| }
|
| break;
|
| - case NON_STRICT_ARGUMENTS_ELEMENTS: {
|
| + case SLOPPY_ARGUMENTS_ELEMENTS: {
|
| // Ascertain whether we have read-only properties or an existing
|
| // getter/setter pair in an arguments elements dictionary backing
|
| // store.
|
| @@ -6213,9 +6202,10 @@ void JSObject::DefinePropertyAccessor(Handle<JSObject> object,
|
| }
|
|
|
|
|
| -bool JSObject::CanSetCallback(Name* name) {
|
| - ASSERT(!IsAccessCheckNeeded() ||
|
| - GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET));
|
| +bool JSObject::CanSetCallback(Handle<JSObject> object, Handle<Name> name) {
|
| + Isolate* isolate = object->GetIsolate();
|
| + ASSERT(!object->IsAccessCheckNeeded() ||
|
| + isolate->MayNamedAccessWrapper(object, name, v8::ACCESS_SET));
|
|
|
| // Check if there is an API defined callback object which prohibits
|
| // callback overwriting in this object or its prototype chain.
|
| @@ -6223,15 +6213,15 @@ bool JSObject::CanSetCallback(Name* name) {
|
| // certain accessors such as window.location should not be allowed
|
| // to be overwritten because allowing overwriting could potentially
|
| // cause security problems.
|
| - LookupResult callback_result(GetIsolate());
|
| - LookupCallbackProperty(name, &callback_result);
|
| + LookupResult callback_result(isolate);
|
| + object->LookupCallbackProperty(*name, &callback_result);
|
| if (callback_result.IsFound()) {
|
| - Object* obj = callback_result.GetCallbackObject();
|
| - if (obj->IsAccessorInfo()) {
|
| - return !AccessorInfo::cast(obj)->prohibits_overwriting();
|
| + Object* callback_obj = callback_result.GetCallbackObject();
|
| + if (callback_obj->IsAccessorInfo()) {
|
| + return !AccessorInfo::cast(callback_obj)->prohibits_overwriting();
|
| }
|
| - if (obj->IsAccessorPair()) {
|
| - return !AccessorPair::cast(obj)->prohibits_overwriting();
|
| + if (callback_obj->IsAccessorPair()) {
|
| + return !AccessorPair::cast(callback_obj)->prohibits_overwriting();
|
| }
|
| }
|
| return true;
|
| @@ -6281,7 +6271,7 @@ void JSObject::SetElementCallback(Handle<JSObject> object,
|
| dictionary->set_requires_slow_elements();
|
|
|
| // Update the dictionary backing store on the object.
|
| - if (object->elements()->map() == heap->non_strict_arguments_elements_map()) {
|
| + if (object->elements()->map() == heap->sloppy_arguments_elements_map()) {
|
| // Also delete any parameter alias.
|
| //
|
| // TODO(kmillikin): when deleting the last parameter alias we could
|
| @@ -6338,8 +6328,8 @@ void JSObject::DefineAccessor(Handle<JSObject> object,
|
| Isolate* isolate = object->GetIsolate();
|
| // Check access rights if needed.
|
| if (object->IsAccessCheckNeeded() &&
|
| - !isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) {
|
| - isolate->ReportFailedAccessCheck(*object, v8::ACCESS_SET);
|
| + !isolate->MayNamedAccessWrapper(object, name, v8::ACCESS_SET)) {
|
| + isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_SET);
|
| return;
|
| }
|
|
|
| @@ -6363,14 +6353,13 @@ void JSObject::DefineAccessor(Handle<JSObject> object,
|
| // Try to flatten before operating on the string.
|
| if (name->IsString()) String::cast(*name)->TryFlatten();
|
|
|
| - if (!object->CanSetCallback(*name)) return;
|
| + if (!JSObject::CanSetCallback(object, name)) return;
|
|
|
| uint32_t index = 0;
|
| bool is_element = name->AsArrayIndex(&index);
|
|
|
| Handle<Object> old_value = isolate->factory()->the_hole_value();
|
| - bool is_observed = FLAG_harmony_observation &&
|
| - object->map()->is_observed() &&
|
| + bool is_observed = object->map()->is_observed() &&
|
| *name != isolate->heap()->hidden_string();
|
| bool preexists = false;
|
| if (is_observed) {
|
| @@ -6404,11 +6393,11 @@ void JSObject::DefineAccessor(Handle<JSObject> object,
|
| }
|
|
|
|
|
| -static bool TryAccessorTransition(JSObject* self,
|
| - Map* transitioned_map,
|
| +static bool TryAccessorTransition(Handle<JSObject> self,
|
| + Handle<Map> transitioned_map,
|
| int target_descriptor,
|
| AccessorComponent component,
|
| - Object* accessor,
|
| + Handle<Object> accessor,
|
| PropertyAttributes attributes) {
|
| DescriptorArray* descs = transitioned_map->instance_descriptors();
|
| PropertyDetails details = descs->GetDetails(target_descriptor);
|
| @@ -6422,8 +6411,8 @@ static bool TryAccessorTransition(JSObject* self,
|
| PropertyAttributes target_attributes = details.attributes();
|
|
|
| // Reuse transition if adding same accessor with same attributes.
|
| - if (target_accessor == accessor && target_attributes == attributes) {
|
| - self->set_map(transitioned_map);
|
| + if (target_accessor == *accessor && target_attributes == attributes) {
|
| + JSObject::MigrateToMap(self, transitioned_map);
|
| return true;
|
| }
|
|
|
| @@ -6485,14 +6474,14 @@ bool JSObject::DefineFastAccessor(Handle<JSObject> object,
|
| object->map()->LookupTransition(*object, *name, &result);
|
|
|
| if (result.IsFound()) {
|
| - Map* target = result.GetTransitionTarget();
|
| + Handle<Map> target(result.GetTransitionTarget());
|
| ASSERT(target->NumberOfOwnDescriptors() ==
|
| object->map()->NumberOfOwnDescriptors());
|
| // This works since descriptors are sorted in order of addition.
|
| ASSERT(object->map()->instance_descriptors()->
|
| GetKey(descriptor_number) == *name);
|
| - return TryAccessorTransition(*object, target, descriptor_number,
|
| - component, *accessor, attributes);
|
| + return TryAccessorTransition(object, target, descriptor_number,
|
| + component, accessor, attributes);
|
| }
|
| } else {
|
| // If not, lookup a transition.
|
| @@ -6500,12 +6489,12 @@ bool JSObject::DefineFastAccessor(Handle<JSObject> object,
|
|
|
| // If there is a transition, try to follow it.
|
| if (result.IsFound()) {
|
| - Map* target = result.GetTransitionTarget();
|
| + Handle<Map> target(result.GetTransitionTarget());
|
| int descriptor_number = target->LastAdded();
|
| ASSERT(target->instance_descriptors()->GetKey(descriptor_number)
|
| ->Equals(*name));
|
| - return TryAccessorTransition(*object, target, descriptor_number,
|
| - component, *accessor, attributes);
|
| + return TryAccessorTransition(object, target, descriptor_number,
|
| + component, accessor, attributes);
|
| }
|
| }
|
|
|
| @@ -6518,7 +6507,7 @@ bool JSObject::DefineFastAccessor(Handle<JSObject> object,
|
| accessors->set(component, *accessor);
|
| Handle<Map> new_map = CopyInsertDescriptor(Handle<Map>(object->map()),
|
| name, accessors, attributes);
|
| - object->set_map(*new_map);
|
| + JSObject::MigrateToMap(object, new_map);
|
| return true;
|
| }
|
|
|
| @@ -6531,8 +6520,8 @@ Handle<Object> JSObject::SetAccessor(Handle<JSObject> object,
|
|
|
| // Check access rights if needed.
|
| if (object->IsAccessCheckNeeded() &&
|
| - !isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) {
|
| - isolate->ReportFailedAccessCheck(*object, v8::ACCESS_SET);
|
| + !isolate->MayNamedAccessWrapper(object, name, v8::ACCESS_SET)) {
|
| + isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_SET);
|
| RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| return factory->undefined_value();
|
| }
|
| @@ -6551,7 +6540,9 @@ Handle<Object> JSObject::SetAccessor(Handle<JSObject> object,
|
| // Try to flatten before operating on the string.
|
| if (name->IsString()) FlattenString(Handle<String>::cast(name));
|
|
|
| - if (!object->CanSetCallback(*name)) return factory->undefined_value();
|
| + if (!JSObject::CanSetCallback(object, name)) {
|
| + return factory->undefined_value();
|
| + }
|
|
|
| uint32_t index = 0;
|
| bool is_element = name->AsArrayIndex(&index);
|
| @@ -6581,7 +6572,7 @@ Handle<Object> JSObject::SetAccessor(Handle<JSObject> object,
|
|
|
| case DICTIONARY_ELEMENTS:
|
| break;
|
| - case NON_STRICT_ARGUMENTS_ELEMENTS:
|
| + case SLOPPY_ARGUMENTS_ELEMENTS:
|
| UNIMPLEMENTED();
|
| break;
|
| }
|
| @@ -6615,8 +6606,8 @@ Handle<Object> JSObject::GetAccessor(Handle<JSObject> object,
|
|
|
| // Check access rights if needed.
|
| if (object->IsAccessCheckNeeded() &&
|
| - !isolate->MayNamedAccess(*object, *name, v8::ACCESS_HAS)) {
|
| - isolate->ReportFailedAccessCheck(*object, v8::ACCESS_HAS);
|
| + !isolate->MayNamedAccessWrapper(object, name, v8::ACCESS_HAS)) {
|
| + isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_HAS);
|
| RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| return isolate->factory()->undefined_value();
|
| }
|
| @@ -6670,8 +6661,7 @@ Object* JSObject::SlowReverseLookup(Object* value) {
|
| for (int i = 0; i < number_of_own_descriptors; i++) {
|
| if (descs->GetType(i) == FIELD) {
|
| Object* property = RawFastPropertyAt(descs->GetFieldIndex(i));
|
| - if (FLAG_track_double_fields &&
|
| - descs->GetDetails(i).representation().IsDouble()) {
|
| + if (descs->GetDetails(i).representation().IsDouble()) {
|
| ASSERT(property->IsHeapNumber());
|
| if (value->IsNumber() && property->Number() == value->Number()) {
|
| return descs->GetKey(i);
|
| @@ -8242,7 +8232,7 @@ static bool IsIdentifier(UnicodeCache* cache, Name* name) {
|
| // Checks whether the buffer contains an identifier (no escape).
|
| if (!name->IsString()) return false;
|
| String* string = String::cast(name);
|
| - if (string->length() == 0) return false;
|
| + if (string->length() == 0) return true;
|
| ConsStringIteratorOp op;
|
| StringCharacterStream stream(string, &op);
|
| if (!cache->IsIdentifierStart(stream.GetNext())) {
|
| @@ -8258,9 +8248,7 @@ static bool IsIdentifier(UnicodeCache* cache, Name* name) {
|
|
|
|
|
| bool Name::IsCacheable(Isolate* isolate) {
|
| - return IsSymbol() ||
|
| - IsIdentifier(isolate->unicode_cache(), this) ||
|
| - this == isolate->heap()->hidden_string();
|
| + return IsSymbol() || IsIdentifier(isolate->unicode_cache(), this);
|
| }
|
|
|
|
|
| @@ -9466,13 +9454,13 @@ bool Map::EquivalentToForNormalization(Map* other,
|
|
|
|
|
| void ConstantPoolArray::ConstantPoolIterateBody(ObjectVisitor* v) {
|
| - if (count_of_ptr_entries() > 0) {
|
| - int first_ptr_offset = OffsetOfElementAt(first_ptr_index());
|
| - int last_ptr_offset =
|
| - OffsetOfElementAt(first_ptr_index() + count_of_ptr_entries() - 1);
|
| - v->VisitPointers(
|
| - HeapObject::RawField(this, first_ptr_offset),
|
| - HeapObject::RawField(this, last_ptr_offset));
|
| + for (int i = 0; i < count_of_code_ptr_entries(); i++) {
|
| + int index = first_code_ptr_index() + i;
|
| + v->VisitCodeEntry(reinterpret_cast<Address>(RawFieldOfElementAt(index)));
|
| + }
|
| + for (int i = 0; i < count_of_heap_ptr_entries(); i++) {
|
| + int index = first_heap_ptr_index() + i;
|
| + v->VisitPointer(RawFieldOfElementAt(index));
|
| }
|
| }
|
|
|
| @@ -9640,38 +9628,42 @@ void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code,
|
| const char* reason) {
|
| if (optimized_code_map()->IsSmi()) return;
|
|
|
| - int i;
|
| - bool removed_entry = false;
|
| FixedArray* code_map = FixedArray::cast(optimized_code_map());
|
| - for (i = kEntriesStart; i < code_map->length(); i += kEntryLength) {
|
| - ASSERT(code_map->get(i)->IsNativeContext());
|
| - if (Code::cast(code_map->get(i + 1)) == optimized_code) {
|
| + int dst = kEntriesStart;
|
| + int length = code_map->length();
|
| + for (int src = kEntriesStart; src < length; src += kEntryLength) {
|
| + ASSERT(code_map->get(src)->IsNativeContext());
|
| + if (Code::cast(code_map->get(src + kCachedCodeOffset)) == optimized_code) {
|
| + // Evict the src entry by not copying it to the dst entry.
|
| if (FLAG_trace_opt) {
|
| PrintF("[evicting entry from optimizing code map (%s) for ", reason);
|
| ShortPrint();
|
| - PrintF("]\n");
|
| + BailoutId osr(Smi::cast(code_map->get(src + kOsrAstIdOffset))->value());
|
| + if (osr.IsNone()) {
|
| + PrintF("]\n");
|
| + } else {
|
| + PrintF(" (osr ast id %d)]\n", osr.ToInt());
|
| + }
|
| }
|
| - removed_entry = true;
|
| - break;
|
| + } else {
|
| + // Keep the src entry by copying it to the dst entry.
|
| + if (dst != src) {
|
| + code_map->set(dst + kContextOffset,
|
| + code_map->get(src + kContextOffset));
|
| + code_map->set(dst + kCachedCodeOffset,
|
| + code_map->get(src + kCachedCodeOffset));
|
| + code_map->set(dst + kLiteralsOffset,
|
| + code_map->get(src + kLiteralsOffset));
|
| + code_map->set(dst + kOsrAstIdOffset,
|
| + code_map->get(src + kOsrAstIdOffset));
|
| + }
|
| + dst += kEntryLength;
|
| }
|
| }
|
| - while (i < (code_map->length() - kEntryLength)) {
|
| - code_map->set(i + kContextOffset,
|
| - code_map->get(i + kContextOffset + kEntryLength));
|
| - code_map->set(i + kCachedCodeOffset,
|
| - code_map->get(i + kCachedCodeOffset + kEntryLength));
|
| - code_map->set(i + kLiteralsOffset,
|
| - code_map->get(i + kLiteralsOffset + kEntryLength));
|
| - code_map->set(i + kOsrAstIdOffset,
|
| - code_map->get(i + kOsrAstIdOffset + kEntryLength));
|
| - i += kEntryLength;
|
| - }
|
| - if (removed_entry) {
|
| + if (dst != length) {
|
| // Always trim even when array is cleared because of heap verifier.
|
| - RightTrimFixedArray<FROM_MUTATOR>(GetHeap(), code_map, kEntryLength);
|
| - if (code_map->length() == kEntriesStart) {
|
| - ClearOptimizedCodeMap();
|
| - }
|
| + RightTrimFixedArray<FROM_MUTATOR>(GetHeap(), code_map, length - dst);
|
| + if (code_map->length() == kEntriesStart) ClearOptimizedCodeMap();
|
| }
|
| }
|
|
|
| @@ -9799,7 +9791,7 @@ void JSFunction::SetPrototype(Handle<JSFunction> function,
|
| // different prototype.
|
| Handle<Map> new_map = Map::Copy(handle(function->map()));
|
|
|
| - function->set_map(*new_map);
|
| + JSObject::MigrateToMap(function, new_map);
|
| new_map->set_constructor(*value);
|
| new_map->set_non_instance_prototype(true);
|
| Isolate* isolate = new_map->GetIsolate();
|
| @@ -9816,15 +9808,15 @@ void JSFunction::SetPrototype(Handle<JSFunction> function,
|
|
|
| void JSFunction::RemovePrototype() {
|
| Context* native_context = context()->native_context();
|
| - Map* no_prototype_map = shared()->is_classic_mode()
|
| - ? native_context->function_without_prototype_map()
|
| - : native_context->strict_mode_function_without_prototype_map();
|
| + Map* no_prototype_map = shared()->strict_mode() == SLOPPY
|
| + ? native_context->sloppy_function_without_prototype_map()
|
| + : native_context->strict_function_without_prototype_map();
|
|
|
| if (map() == no_prototype_map) return;
|
|
|
| - ASSERT(map() == (shared()->is_classic_mode()
|
| - ? native_context->function_map()
|
| - : native_context->strict_mode_function_map()));
|
| + ASSERT(map() == (shared()->strict_mode() == SLOPPY
|
| + ? native_context->sloppy_function_map()
|
| + : native_context->strict_function_map()));
|
|
|
| set_map(no_prototype_map);
|
| set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
|
| @@ -10642,26 +10634,24 @@ void Code::ClearInlineCaches(Code::Kind* kind) {
|
| Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
|
| if (target->is_inline_cache_stub()) {
|
| if (kind == NULL || *kind == target->kind()) {
|
| - IC::Clear(this->GetIsolate(), info->pc());
|
| + IC::Clear(this->GetIsolate(), info->pc(),
|
| + info->host()->constant_pool());
|
| }
|
| }
|
| }
|
| }
|
|
|
|
|
| -void Code::ClearTypeFeedbackInfo(Heap* heap) {
|
| - if (kind() != FUNCTION) return;
|
| - Object* raw_info = type_feedback_info();
|
| - if (raw_info->IsTypeFeedbackInfo()) {
|
| - FixedArray* feedback_vector =
|
| - TypeFeedbackInfo::cast(raw_info)->feedback_vector();
|
| - for (int i = 0; i < feedback_vector->length(); i++) {
|
| - Object* obj = feedback_vector->get(i);
|
| - if (!obj->IsAllocationSite()) {
|
| - // TODO(mvstanton): Can't I avoid a write barrier for this sentinel?
|
| - feedback_vector->set(i,
|
| - TypeFeedbackInfo::RawUninitializedSentinel(heap));
|
| - }
|
| +void SharedFunctionInfo::ClearTypeFeedbackInfo(Heap* heap) {
|
| + FixedArray* vector = feedback_vector();
|
| + for (int i = 0; i < vector->length(); i++) {
|
| + Object* obj = vector->get(i);
|
| + if (!obj->IsAllocationSite()) {
|
| + // The assert verifies we can skip the write barrier.
|
| + ASSERT(heap->uninitialized_symbol() ==
|
| + TypeFeedbackInfo::RawUninitializedSentinel(heap));
|
| + vector->set(i, TypeFeedbackInfo::RawUninitializedSentinel(heap),
|
| + SKIP_WRITE_BARRIER);
|
| }
|
| }
|
| }
|
| @@ -11086,9 +11076,7 @@ void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) {
|
| switch (kind) {
|
| case STORE_IC:
|
| case KEYED_STORE_IC:
|
| - if (extra == kStrictMode) {
|
| - name = "STRICT";
|
| - }
|
| + if (extra == STRICT) name = "STRICT";
|
| break;
|
| default:
|
| break;
|
| @@ -11255,7 +11243,7 @@ MaybeObject* JSObject::SetFastElementsCapacityAndLength(
|
| accessor->CopyElements(this, new_elements, elements_kind);
|
| if (maybe_obj->IsFailure()) return maybe_obj;
|
|
|
| - if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {
|
| + if (elements_kind != SLOPPY_ARGUMENTS_ELEMENTS) {
|
| Map* new_map = map();
|
| if (new_elements_kind != elements_kind) {
|
| MaybeObject* maybe =
|
| @@ -11327,7 +11315,7 @@ MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength(
|
| accessor->CopyElements(this, elems, elements_kind);
|
| if (maybe_obj->IsFailure()) return maybe_obj;
|
| }
|
| - if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {
|
| + if (elements_kind != SLOPPY_ARGUMENTS_ELEMENTS) {
|
| ValidateElements();
|
| set_map_and_elements(new_map, elems);
|
| } else {
|
| @@ -11369,7 +11357,8 @@ static bool GetOldValue(Isolate* isolate,
|
| uint32_t index,
|
| List<Handle<Object> >* old_values,
|
| List<uint32_t>* indices) {
|
| - PropertyAttributes attributes = object->GetLocalElementAttribute(index);
|
| + PropertyAttributes attributes =
|
| + JSReceiver::GetLocalElementAttribute(object, index);
|
| ASSERT(attributes != ABSENT);
|
| if (attributes == DONT_DELETE) return false;
|
| old_values->Add(object->GetLocalElementAccessorPair(index) == NULL
|
| @@ -11432,7 +11421,7 @@ static void EndPerformSplice(Handle<JSArray> object) {
|
| MaybeObject* JSArray::SetElementsLength(Object* len) {
|
| // We should never end in here with a pixel or external array.
|
| ASSERT(AllowsSetElementsLength());
|
| - if (!(FLAG_harmony_observation && map()->is_observed()))
|
| + if (!map()->is_observed())
|
| return GetElementsAccessor()->SetLength(this, len);
|
|
|
| Isolate* isolate = GetIsolate();
|
| @@ -11498,12 +11487,12 @@ MaybeObject* JSArray::SetElementsLength(Object* len) {
|
| if (delete_count > 0) {
|
| for (int i = indices.length() - 1; i >= 0; i--) {
|
| JSObject::SetElement(deleted, indices[i] - index, old_values[i], NONE,
|
| - kNonStrictMode);
|
| + SLOPPY);
|
| }
|
|
|
| SetProperty(deleted, isolate->factory()->length_string(),
|
| isolate->factory()->NewNumberFromUint(delete_count),
|
| - NONE, kNonStrictMode);
|
| + NONE, SLOPPY);
|
| }
|
|
|
| EnqueueSpliceRecord(self, index, deleted, add_count);
|
| @@ -11876,7 +11865,7 @@ Handle<Object> JSObject::SetPrototype(Handle<JSObject> object,
|
| new_map->set_prototype(*value);
|
| }
|
| ASSERT(new_map->prototype() == *value);
|
| - real_receiver->set_map(*new_map);
|
| + JSObject::MigrateToMap(real_receiver, new_map);
|
|
|
| if (!dictionary_elements_in_chain &&
|
| new_map->DictionaryElementsInPrototypeChainOnly()) {
|
| @@ -11942,7 +11931,7 @@ Handle<Object> JSObject::SetElementWithInterceptor(
|
| uint32_t index,
|
| Handle<Object> value,
|
| PropertyAttributes attributes,
|
| - StrictModeFlag strict_mode,
|
| + StrictMode strict_mode,
|
| bool check_prototype,
|
| SetPropertyMode set_mode) {
|
| Isolate* isolate = object->GetIsolate();
|
| @@ -12030,7 +12019,7 @@ Handle<Object> JSObject::SetElementWithCallback(Handle<JSObject> object,
|
| uint32_t index,
|
| Handle<Object> value,
|
| Handle<JSObject> holder,
|
| - StrictModeFlag strict_mode) {
|
| + StrictMode strict_mode) {
|
| Isolate* isolate = object->GetIsolate();
|
|
|
| // We should never get here to initialize a const with the hole
|
| @@ -12069,9 +12058,7 @@ Handle<Object> JSObject::SetElementWithCallback(Handle<JSObject> object,
|
| return SetPropertyWithDefinedSetter(
|
| object, Handle<JSReceiver>::cast(setter), value);
|
| } else {
|
| - if (strict_mode == kNonStrictMode) {
|
| - return value;
|
| - }
|
| + if (strict_mode == SLOPPY) return value;
|
| Handle<Object> key(isolate->factory()->NewNumberFromUint(index));
|
| Handle<Object> args[2] = { key, holder };
|
| Handle<Object> error = isolate->factory()->NewTypeError(
|
| @@ -12093,7 +12080,7 @@ bool JSObject::HasFastArgumentsElements() {
|
| Heap* heap = GetHeap();
|
| if (!elements()->IsFixedArray()) return false;
|
| FixedArray* elements = FixedArray::cast(this->elements());
|
| - if (elements->map() != heap->non_strict_arguments_elements_map()) {
|
| + if (elements->map() != heap->sloppy_arguments_elements_map()) {
|
| return false;
|
| }
|
| FixedArray* arguments = FixedArray::cast(elements->get(1));
|
| @@ -12105,7 +12092,7 @@ bool JSObject::HasDictionaryArgumentsElements() {
|
| Heap* heap = GetHeap();
|
| if (!elements()->IsFixedArray()) return false;
|
| FixedArray* elements = FixedArray::cast(this->elements());
|
| - if (elements->map() != heap->non_strict_arguments_elements_map()) {
|
| + if (elements->map() != heap->sloppy_arguments_elements_map()) {
|
| return false;
|
| }
|
| FixedArray* arguments = FixedArray::cast(elements->get(1));
|
| @@ -12119,7 +12106,7 @@ bool JSObject::HasDictionaryArgumentsElements() {
|
| Handle<Object> JSObject::SetFastElement(Handle<JSObject> object,
|
| uint32_t index,
|
| Handle<Object> value,
|
| - StrictModeFlag strict_mode,
|
| + StrictMode strict_mode,
|
| bool check_prototype) {
|
| ASSERT(object->HasFastSmiOrObjectElements() ||
|
| object->HasFastArgumentsElements());
|
| @@ -12137,7 +12124,7 @@ Handle<Object> JSObject::SetFastElement(Handle<JSObject> object,
|
|
|
| Handle<FixedArray> backing_store(FixedArray::cast(object->elements()));
|
| if (backing_store->map() ==
|
| - isolate->heap()->non_strict_arguments_elements_map()) {
|
| + isolate->heap()->sloppy_arguments_elements_map()) {
|
| backing_store = handle(FixedArray::cast(backing_store->get(1)));
|
| } else {
|
| backing_store = EnsureWritableFastElements(object);
|
| @@ -12217,7 +12204,7 @@ Handle<Object> JSObject::SetFastElement(Handle<JSObject> object,
|
|
|
| UpdateAllocationSite(object, kind);
|
| Handle<Map> new_map = GetElementsTransitionMap(object, kind);
|
| - object->set_map(*new_map);
|
| + JSObject::MigrateToMap(object, new_map);
|
| ASSERT(IsFastObjectElementsKind(object->GetElementsKind()));
|
| }
|
| // Increase backing store capacity if that's been decided previously.
|
| @@ -12248,7 +12235,7 @@ Handle<Object> JSObject::SetDictionaryElement(Handle<JSObject> object,
|
| uint32_t index,
|
| Handle<Object> value,
|
| PropertyAttributes attributes,
|
| - StrictModeFlag strict_mode,
|
| + StrictMode strict_mode,
|
| bool check_prototype,
|
| SetPropertyMode set_mode) {
|
| ASSERT(object->HasDictionaryElements() ||
|
| @@ -12258,7 +12245,7 @@ Handle<Object> JSObject::SetDictionaryElement(Handle<JSObject> object,
|
| // Insert element in the dictionary.
|
| Handle<FixedArray> elements(FixedArray::cast(object->elements()));
|
| bool is_arguments =
|
| - (elements->map() == isolate->heap()->non_strict_arguments_elements_map());
|
| + (elements->map() == isolate->heap()->sloppy_arguments_elements_map());
|
| Handle<SeededNumberDictionary> dictionary(is_arguments
|
| ? SeededNumberDictionary::cast(elements->get(1))
|
| : SeededNumberDictionary::cast(*elements));
|
| @@ -12280,7 +12267,7 @@ Handle<Object> JSObject::SetDictionaryElement(Handle<JSObject> object,
|
| attributes, NORMAL, details.dictionary_index());
|
| dictionary->DetailsAtPut(entry, details);
|
| } else if (details.IsReadOnly() && !element->IsTheHole()) {
|
| - if (strict_mode == kNonStrictMode) {
|
| + if (strict_mode == SLOPPY) {
|
| return isolate->factory()->undefined_value();
|
| } else {
|
| Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
|
| @@ -12318,7 +12305,7 @@ Handle<Object> JSObject::SetDictionaryElement(Handle<JSObject> object,
|
| // When we set the is_extensible flag to false we always force the
|
| // element into dictionary mode (and force them to stay there).
|
| if (!object->map()->is_extensible()) {
|
| - if (strict_mode == kNonStrictMode) {
|
| + if (strict_mode == SLOPPY) {
|
| return isolate->factory()->undefined_value();
|
| } else {
|
| Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
|
| @@ -12391,7 +12378,7 @@ Handle<Object> JSObject::SetFastDoubleElement(
|
| Handle<JSObject> object,
|
| uint32_t index,
|
| Handle<Object> value,
|
| - StrictModeFlag strict_mode,
|
| + StrictMode strict_mode,
|
| bool check_prototype) {
|
| ASSERT(object->HasFastDoubleElements());
|
|
|
| @@ -12489,7 +12476,7 @@ Handle<Object> JSReceiver::SetElement(Handle<JSReceiver> object,
|
| uint32_t index,
|
| Handle<Object> value,
|
| PropertyAttributes attributes,
|
| - StrictModeFlag strict_mode) {
|
| + StrictMode strict_mode) {
|
| if (object->IsJSProxy()) {
|
| return JSProxy::SetElementWithHandler(
|
| Handle<JSProxy>::cast(object), object, index, value, strict_mode);
|
| @@ -12502,7 +12489,7 @@ Handle<Object> JSReceiver::SetElement(Handle<JSReceiver> object,
|
| Handle<Object> JSObject::SetOwnElement(Handle<JSObject> object,
|
| uint32_t index,
|
| Handle<Object> value,
|
| - StrictModeFlag strict_mode) {
|
| + StrictMode strict_mode) {
|
| ASSERT(!object->HasExternalArrayElements());
|
| return JSObject::SetElement(object, index, value, NONE, strict_mode, false);
|
| }
|
| @@ -12512,7 +12499,7 @@ Handle<Object> JSObject::SetElement(Handle<JSObject> object,
|
| uint32_t index,
|
| Handle<Object> value,
|
| PropertyAttributes attributes,
|
| - StrictModeFlag strict_mode,
|
| + StrictMode strict_mode,
|
| bool check_prototype,
|
| SetPropertyMode set_mode) {
|
| Isolate* isolate = object->GetIsolate();
|
| @@ -12529,8 +12516,8 @@ Handle<Object> JSObject::SetElement(Handle<JSObject> object,
|
|
|
| // Check access rights if needed.
|
| if (object->IsAccessCheckNeeded()) {
|
| - if (!isolate->MayIndexedAccess(*object, index, v8::ACCESS_SET)) {
|
| - isolate->ReportFailedAccessCheck(*object, v8::ACCESS_SET);
|
| + if (!isolate->MayIndexedAccessWrapper(object, index, v8::ACCESS_SET)) {
|
| + isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_SET);
|
| RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| return value;
|
| }
|
| @@ -12563,7 +12550,7 @@ Handle<Object> JSObject::SetElement(Handle<JSObject> object,
|
| dictionary->set_requires_slow_elements();
|
| }
|
|
|
| - if (!(FLAG_harmony_observation && object->map()->is_observed())) {
|
| + if (!object->map()->is_observed()) {
|
| return object->HasIndexedInterceptor()
|
| ? SetElementWithInterceptor(object, index, value, attributes, strict_mode,
|
| check_prototype,
|
| @@ -12574,7 +12561,8 @@ Handle<Object> JSObject::SetElement(Handle<JSObject> object,
|
| set_mode);
|
| }
|
|
|
| - PropertyAttributes old_attributes = object->GetLocalElementAttribute(index);
|
| + PropertyAttributes old_attributes =
|
| + JSReceiver::GetLocalElementAttribute(object, index);
|
| Handle<Object> old_value = isolate->factory()->the_hole_value();
|
| Handle<Object> old_length_handle;
|
| Handle<Object> new_length_handle;
|
| @@ -12600,7 +12588,7 @@ Handle<Object> JSObject::SetElement(Handle<JSObject> object,
|
| RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>());
|
|
|
| Handle<String> name = isolate->factory()->Uint32ToString(index);
|
| - PropertyAttributes new_attributes = object->GetLocalElementAttribute(index);
|
| + PropertyAttributes new_attributes = GetLocalElementAttribute(object, index);
|
| if (old_attributes == ABSENT) {
|
| if (object->IsJSArray() &&
|
| !old_length_handle->SameValue(
|
| @@ -12645,7 +12633,7 @@ Handle<Object> JSObject::SetElementWithoutInterceptor(
|
| uint32_t index,
|
| Handle<Object> value,
|
| PropertyAttributes attributes,
|
| - StrictModeFlag strict_mode,
|
| + StrictMode strict_mode,
|
| bool check_prototype,
|
| SetPropertyMode set_mode) {
|
| ASSERT(object->HasDictionaryElements() ||
|
| @@ -12693,7 +12681,7 @@ Handle<Object> JSObject::SetElementWithoutInterceptor(
|
| return SetDictionaryElement(object, index, value, attributes, strict_mode,
|
| check_prototype,
|
| set_mode);
|
| - case NON_STRICT_ARGUMENTS_ELEMENTS: {
|
| + case SLOPPY_ARGUMENTS_ELEMENTS: {
|
| Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
|
| uint32_t length = parameter_map->length();
|
| Handle<Object> probe = index < length - 2 ?
|
| @@ -12906,6 +12894,7 @@ MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) {
|
| MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind);
|
| Map* new_map;
|
| if (!maybe_new_map->To(&new_map)) return maybe_new_map;
|
| + // TODO(verwaest): Replace by MigrateToMap.
|
| set_map(new_map);
|
| if (FLAG_trace_elements_transitions) {
|
| FixedArrayBase* elms = FixedArrayBase::cast(elements());
|
| @@ -13052,7 +13041,7 @@ void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) {
|
| FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements());
|
| FixedArray* backing_store = NULL;
|
| switch (GetElementsKind()) {
|
| - case NON_STRICT_ARGUMENTS_ELEMENTS:
|
| + case SLOPPY_ARGUMENTS_ELEMENTS:
|
| backing_store_base =
|
| FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
|
| backing_store = FixedArray::cast(backing_store_base);
|
| @@ -13120,6 +13109,21 @@ void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) {
|
| }
|
|
|
|
|
| +bool JSObject::WouldConvertToSlowElements(Handle<Object> key) {
|
| + uint32_t index;
|
| + if (HasFastElements() && key->ToArrayIndex(&index)) {
|
| + Handle<FixedArrayBase> backing_store(FixedArrayBase::cast(elements()));
|
| + uint32_t capacity = static_cast<uint32_t>(backing_store->length());
|
| + if (index >= capacity) {
|
| + if ((index - capacity) >= kMaxGap) return true;
|
| + uint32_t new_capacity = NewElementsCapacity(index + 1);
|
| + return ShouldConvertToSlowElements(new_capacity);
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +
|
| bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
|
| STATIC_ASSERT(kMaxUncheckedOldFastElementsLength <=
|
| kMaxUncheckedFastElementsLength);
|
| @@ -13149,11 +13153,11 @@ bool JSObject::ShouldConvertToFastElements() {
|
| if (IsAccessCheckNeeded()) return false;
|
| // Observed objects may not go to fast mode because they rely on map checks,
|
| // and for fast element accesses we sometimes check element kinds only.
|
| - if (FLAG_harmony_observation && map()->is_observed()) return false;
|
| + if (map()->is_observed()) return false;
|
|
|
| FixedArray* elements = FixedArray::cast(this->elements());
|
| SeededNumberDictionary* dictionary = NULL;
|
| - if (elements->map() == GetHeap()->non_strict_arguments_elements_map()) {
|
| + if (elements->map() == GetHeap()->sloppy_arguments_elements_map()) {
|
| dictionary = SeededNumberDictionary::cast(elements->get(1));
|
| } else {
|
| dictionary = SeededNumberDictionary::cast(elements);
|
| @@ -13343,8 +13347,8 @@ bool JSObject::HasRealNamedProperty(Handle<JSObject> object,
|
| SealHandleScope shs(isolate);
|
| // Check access rights if needed.
|
| if (object->IsAccessCheckNeeded()) {
|
| - if (!isolate->MayNamedAccess(*object, *key, v8::ACCESS_HAS)) {
|
| - isolate->ReportFailedAccessCheck(*object, v8::ACCESS_HAS);
|
| + if (!isolate->MayNamedAccessWrapper(object, key, v8::ACCESS_HAS)) {
|
| + isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_HAS);
|
| return false;
|
| }
|
| }
|
| @@ -13357,11 +13361,11 @@ bool JSObject::HasRealNamedProperty(Handle<JSObject> object,
|
|
|
| bool JSObject::HasRealElementProperty(Handle<JSObject> object, uint32_t index) {
|
| Isolate* isolate = object->GetIsolate();
|
| - SealHandleScope shs(isolate);
|
| + HandleScope scope(isolate);
|
| // Check access rights if needed.
|
| if (object->IsAccessCheckNeeded()) {
|
| - if (!isolate->MayIndexedAccess(*object, index, v8::ACCESS_HAS)) {
|
| - isolate->ReportFailedAccessCheck(*object, v8::ACCESS_HAS);
|
| + if (!isolate->MayIndexedAccessWrapper(object, index, v8::ACCESS_HAS)) {
|
| + isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_HAS);
|
| return false;
|
| }
|
| }
|
| @@ -13374,8 +13378,8 @@ bool JSObject::HasRealElementProperty(Handle<JSObject> object, uint32_t index) {
|
| return HasRealElementProperty(Handle<JSObject>::cast(proto), index);
|
| }
|
|
|
| - return object->GetElementAttributeWithoutInterceptor(
|
| - *object, index, false) != ABSENT;
|
| + return GetElementAttributeWithoutInterceptor(
|
| + object, object, index, false) != ABSENT;
|
| }
|
|
|
|
|
| @@ -13385,8 +13389,8 @@ bool JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object,
|
| SealHandleScope shs(isolate);
|
| // Check access rights if needed.
|
| if (object->IsAccessCheckNeeded()) {
|
| - if (!isolate->MayNamedAccess(*object, *key, v8::ACCESS_HAS)) {
|
| - isolate->ReportFailedAccessCheck(*object, v8::ACCESS_HAS);
|
| + if (!isolate->MayNamedAccessWrapper(object, key, v8::ACCESS_HAS)) {
|
| + isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_HAS);
|
| return false;
|
| }
|
| }
|
| @@ -13633,7 +13637,7 @@ int JSObject::GetLocalElementKeys(FixedArray* storage,
|
| counter += element_dictionary()->NumberOfElementsFilterAttributes(filter);
|
| break;
|
| }
|
| - case NON_STRICT_ARGUMENTS_ELEMENTS: {
|
| + case SLOPPY_ARGUMENTS_ELEMENTS: {
|
| FixedArray* parameter_map = FixedArray::cast(elements());
|
| int mapped_length = parameter_map->length() - 2;
|
| FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
|
| @@ -13731,11 +13735,11 @@ class StringSharedKey : public HashTableKey {
|
| public:
|
| StringSharedKey(String* source,
|
| SharedFunctionInfo* shared,
|
| - LanguageMode language_mode,
|
| + StrictMode strict_mode,
|
| int scope_position)
|
| : source_(source),
|
| shared_(shared),
|
| - language_mode_(language_mode),
|
| + strict_mode_(strict_mode),
|
| scope_position_(scope_position) { }
|
|
|
| bool IsMatch(Object* other) {
|
| @@ -13743,12 +13747,10 @@ class StringSharedKey : public HashTableKey {
|
| FixedArray* other_array = FixedArray::cast(other);
|
| SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
|
| if (shared != shared_) return false;
|
| - int language_unchecked = Smi::cast(other_array->get(2))->value();
|
| - ASSERT(language_unchecked == CLASSIC_MODE ||
|
| - language_unchecked == STRICT_MODE ||
|
| - language_unchecked == EXTENDED_MODE);
|
| - LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
|
| - if (language_mode != language_mode_) return false;
|
| + int strict_unchecked = Smi::cast(other_array->get(2))->value();
|
| + ASSERT(strict_unchecked == SLOPPY || strict_unchecked == STRICT);
|
| + StrictMode strict_mode = static_cast<StrictMode>(strict_unchecked);
|
| + if (strict_mode != strict_mode_) return false;
|
| int scope_position = Smi::cast(other_array->get(3))->value();
|
| if (scope_position != scope_position_) return false;
|
| String* source = String::cast(other_array->get(1));
|
| @@ -13757,7 +13759,7 @@ class StringSharedKey : public HashTableKey {
|
|
|
| static uint32_t StringSharedHashHelper(String* source,
|
| SharedFunctionInfo* shared,
|
| - LanguageMode language_mode,
|
| + StrictMode strict_mode,
|
| int scope_position) {
|
| uint32_t hash = source->Hash();
|
| if (shared->HasSourceCode()) {
|
| @@ -13768,8 +13770,7 @@ class StringSharedKey : public HashTableKey {
|
| // collection.
|
| Script* script = Script::cast(shared->script());
|
| hash ^= String::cast(script->source())->Hash();
|
| - if (language_mode == STRICT_MODE) hash ^= 0x8000;
|
| - if (language_mode == EXTENDED_MODE) hash ^= 0x0080;
|
| + if (strict_mode == STRICT) hash ^= 0x8000;
|
| hash += scope_position;
|
| }
|
| return hash;
|
| @@ -13777,21 +13778,19 @@ class StringSharedKey : public HashTableKey {
|
|
|
| uint32_t Hash() {
|
| return StringSharedHashHelper(
|
| - source_, shared_, language_mode_, scope_position_);
|
| + source_, shared_, strict_mode_, scope_position_);
|
| }
|
|
|
| uint32_t HashForObject(Object* obj) {
|
| FixedArray* other_array = FixedArray::cast(obj);
|
| SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
|
| String* source = String::cast(other_array->get(1));
|
| - int language_unchecked = Smi::cast(other_array->get(2))->value();
|
| - ASSERT(language_unchecked == CLASSIC_MODE ||
|
| - language_unchecked == STRICT_MODE ||
|
| - language_unchecked == EXTENDED_MODE);
|
| - LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
|
| + int strict_unchecked = Smi::cast(other_array->get(2))->value();
|
| + ASSERT(strict_unchecked == SLOPPY || strict_unchecked == STRICT);
|
| + StrictMode strict_mode = static_cast<StrictMode>(strict_unchecked);
|
| int scope_position = Smi::cast(other_array->get(3))->value();
|
| return StringSharedHashHelper(
|
| - source, shared, language_mode, scope_position);
|
| + source, shared, strict_mode, scope_position);
|
| }
|
|
|
| MUST_USE_RESULT MaybeObject* AsObject(Heap* heap) {
|
| @@ -13802,7 +13801,7 @@ class StringSharedKey : public HashTableKey {
|
| FixedArray* other_array = FixedArray::cast(obj);
|
| other_array->set(0, shared_);
|
| other_array->set(1, source_);
|
| - other_array->set(2, Smi::FromInt(language_mode_));
|
| + other_array->set(2, Smi::FromInt(strict_mode_));
|
| other_array->set(3, Smi::FromInt(scope_position_));
|
| return other_array;
|
| }
|
| @@ -13810,7 +13809,7 @@ class StringSharedKey : public HashTableKey {
|
| private:
|
| String* source_;
|
| SharedFunctionInfo* shared_;
|
| - LanguageMode language_mode_;
|
| + StrictMode strict_mode_;
|
| int scope_position_;
|
| };
|
|
|
| @@ -14446,8 +14445,11 @@ MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) {
|
| Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object,
|
| uint32_t limit) {
|
| Isolate* isolate = object->GetIsolate();
|
| + if (object->HasSloppyArgumentsElements() ||
|
| + object->map()->is_observed()) {
|
| + return handle(Smi::FromInt(-1), isolate);
|
| + }
|
|
|
| - ASSERT(!object->map()->is_observed());
|
| if (object->HasDictionaryElements()) {
|
| // Convert to fast elements containing only the existing properties.
|
| // Ordering is irrelevant, since we are going to sort anyway.
|
| @@ -15003,22 +15005,11 @@ MaybeObject* StringTable::LookupKey(HashTableKey* key, Object** s) {
|
| }
|
|
|
|
|
| -// The key for the script compilation cache is dependent on the mode flags,
|
| -// because they change the global language mode and thus binding behaviour.
|
| -// If flags change at some point, we must ensure that we do not hit the cache
|
| -// for code compiled with different settings.
|
| -static LanguageMode CurrentGlobalLanguageMode() {
|
| - return FLAG_use_strict
|
| - ? (FLAG_harmony_scoping ? EXTENDED_MODE : STRICT_MODE)
|
| - : CLASSIC_MODE;
|
| -}
|
| -
|
| -
|
| Object* CompilationCacheTable::Lookup(String* src, Context* context) {
|
| SharedFunctionInfo* shared = context->closure()->shared();
|
| StringSharedKey key(src,
|
| shared,
|
| - CurrentGlobalLanguageMode(),
|
| + FLAG_use_strict ? STRICT : SLOPPY,
|
| RelocInfo::kNoPosition);
|
| int entry = FindEntry(&key);
|
| if (entry == kNotFound) return GetHeap()->undefined_value();
|
| @@ -15028,11 +15019,11 @@ Object* CompilationCacheTable::Lookup(String* src, Context* context) {
|
|
|
| Object* CompilationCacheTable::LookupEval(String* src,
|
| Context* context,
|
| - LanguageMode language_mode,
|
| + StrictMode strict_mode,
|
| int scope_position) {
|
| StringSharedKey key(src,
|
| context->closure()->shared(),
|
| - language_mode,
|
| + strict_mode,
|
| scope_position);
|
| int entry = FindEntry(&key);
|
| if (entry == kNotFound) return GetHeap()->undefined_value();
|
| @@ -15055,7 +15046,7 @@ MaybeObject* CompilationCacheTable::Put(String* src,
|
| SharedFunctionInfo* shared = context->closure()->shared();
|
| StringSharedKey key(src,
|
| shared,
|
| - CurrentGlobalLanguageMode(),
|
| + FLAG_use_strict ? STRICT : SLOPPY,
|
| RelocInfo::kNoPosition);
|
| CompilationCacheTable* cache;
|
| MaybeObject* maybe_cache = EnsureCapacity(1, &key);
|
| @@ -15079,7 +15070,7 @@ MaybeObject* CompilationCacheTable::PutEval(String* src,
|
| int scope_position) {
|
| StringSharedKey key(src,
|
| context->closure()->shared(),
|
| - value->language_mode(),
|
| + value->strict_mode(),
|
| scope_position);
|
| Object* obj;
|
| { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
|
| @@ -15522,7 +15513,7 @@ int Dictionary<Shape, Key>::NumberOfElementsFilterAttributes(
|
| template<typename Shape, typename Key>
|
| int Dictionary<Shape, Key>::NumberOfEnumElements() {
|
| return NumberOfElementsFilterAttributes(
|
| - static_cast<PropertyAttributes>(DONT_ENUM));
|
| + static_cast<PropertyAttributes>(DONT_ENUM | SYMBOLIC));
|
| }
|
|
|
|
|
| @@ -15550,45 +15541,38 @@ void Dictionary<Shape, Key>::CopyKeysTo(
|
| }
|
|
|
|
|
| -FixedArray* NameDictionary::CopyEnumKeysTo(FixedArray* storage) {
|
| +struct EnumIndexComparator {
|
| + explicit EnumIndexComparator(NameDictionary* dict) : dict(dict) { }
|
| + bool operator() (Smi* a, Smi* b) {
|
| + PropertyDetails da(dict->DetailsAt(a->value()));
|
| + PropertyDetails db(dict->DetailsAt(b->value()));
|
| + return da.dictionary_index() < db.dictionary_index();
|
| + }
|
| + NameDictionary* dict;
|
| +};
|
| +
|
| +
|
| +void NameDictionary::CopyEnumKeysTo(FixedArray* storage) {
|
| int length = storage->length();
|
| - ASSERT(length >= NumberOfEnumElements());
|
| - Heap* heap = GetHeap();
|
| - Object* undefined_value = heap->undefined_value();
|
| int capacity = Capacity();
|
| int properties = 0;
|
| -
|
| - // Fill in the enumeration array by assigning enumerable keys at their
|
| - // enumeration index. This will leave holes in the array if there are keys
|
| - // that are deleted or not enumerable.
|
| for (int i = 0; i < capacity; i++) {
|
| Object* k = KeyAt(i);
|
| if (IsKey(k) && !k->IsSymbol()) {
|
| PropertyDetails details = DetailsAt(i);
|
| if (details.IsDeleted() || details.IsDontEnum()) continue;
|
| + storage->set(properties, Smi::FromInt(i));
|
| properties++;
|
| - storage->set(details.dictionary_index() - 1, k);
|
| if (properties == length) break;
|
| }
|
| }
|
| -
|
| - // There are holes in the enumeration array if less properties were assigned
|
| - // than the length of the array. If so, crunch all the existing properties
|
| - // together by shifting them to the left (maintaining the enumeration order),
|
| - // and trimming of the right side of the array.
|
| - if (properties < length) {
|
| - if (properties == 0) return heap->empty_fixed_array();
|
| - properties = 0;
|
| - for (int i = 0; i < length; ++i) {
|
| - Object* value = storage->get(i);
|
| - if (value != undefined_value) {
|
| - storage->set(properties, value);
|
| - ++properties;
|
| - }
|
| - }
|
| - RightTrimFixedArray<FROM_MUTATOR>(heap, storage, length - properties);
|
| + EnumIndexComparator cmp(this);
|
| + Smi** start = reinterpret_cast<Smi**>(storage->GetFirstElementAddress());
|
| + std::sort(start, start + length, cmp);
|
| + for (int i = 0; i < length; i++) {
|
| + int index = Smi::cast(storage->get(i))->value();
|
| + storage->set(i, KeyAt(index));
|
| }
|
| - return storage;
|
| }
|
|
|
|
|
| @@ -15724,7 +15708,6 @@ MaybeObject* NameDictionary::TransformPropertiesToFastFor(
|
| // instance descriptor.
|
| MaybeObject* maybe_key = heap->InternalizeString(String::cast(k));
|
| if (!maybe_key->To(&key)) return maybe_key;
|
| - if (key->Equals(heap->empty_string())) return this;
|
| }
|
|
|
| PropertyDetails details = DetailsAt(i);
|
|
|