Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(462)

Unified Diff: src/objects.cc

Issue 6614010: [Isolates] Merge 6700:7030 from bleeding_edge to isolates. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/isolates/
Patch Set: '' Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/objects.cc
===================================================================
--- src/objects.cc (revision 7031)
+++ src/objects.cc (working copy)
@@ -550,10 +550,25 @@
MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) {
- // Non-JS objects do not have integer indexed properties.
- if (!IsJSObject()) return Isolate::Current()->heap()->undefined_value();
- return JSObject::cast(this)->GetElementWithReceiver(JSObject::cast(receiver),
- index);
+ if (IsJSObject()) {
+ return JSObject::cast(this)->GetElementWithReceiver(receiver, index);
+ }
+
+ Object* holder = NULL;
+ Context* global_context = Isolate::Current()->context()->global_context();
+ if (IsString()) {
+ holder = global_context->string_function()->instance_prototype();
+ } else if (IsNumber()) {
+ holder = global_context->number_function()->instance_prototype();
+ } else if (IsBoolean()) {
+ holder = global_context->boolean_function()->instance_prototype();
+ } else {
+ // Undefined and null have no indexed properties.
+ ASSERT(IsUndefined() || IsNull());
+ return HEAP->undefined_value();
+ }
+
+ return JSObject::cast(holder)->GetElementWithReceiver(receiver, index);
}
@@ -1458,14 +1473,15 @@
MaybeObject* JSObject::SetPropertyPostInterceptor(
String* name,
Object* value,
- PropertyAttributes attributes) {
+ PropertyAttributes attributes,
+ StrictModeFlag strict) {
// Check local property, ignore interceptor.
LookupResult result;
LocalLookupRealNamedProperty(name, &result);
if (result.IsFound()) {
// An existing property, a map transition or a null descriptor was
// found. Use set property to handle all these cases.
- return SetProperty(&result, name, value, attributes);
+ return SetProperty(&result, name, value, attributes, strict);
}
// Add a new real property.
return AddProperty(name, value, attributes);
@@ -1591,7 +1607,8 @@
MaybeObject* JSObject::SetPropertyWithInterceptor(
String* name,
Object* value,
- PropertyAttributes attributes) {
+ PropertyAttributes attributes,
+ StrictModeFlag strict) {
Isolate* isolate = GetIsolate();
HandleScope scope(isolate);
Handle<JSObject> this_handle(this);
@@ -1622,7 +1639,8 @@
MaybeObject* raw_result =
this_handle->SetPropertyPostInterceptor(*name_handle,
*value_handle,
- attributes);
+ attributes,
+ strict);
RETURN_IF_SCHEDULED_EXCEPTION(isolate);
return raw_result;
}
@@ -1630,10 +1648,11 @@
MaybeObject* JSObject::SetProperty(String* name,
Object* value,
- PropertyAttributes attributes) {
+ PropertyAttributes attributes,
+ StrictModeFlag strict) {
LookupResult result;
LocalLookup(name, &result);
- return SetProperty(&result, name, value, attributes);
+ return SetProperty(&result, name, value, attributes, strict);
}
@@ -1922,7 +1941,8 @@
MaybeObject* JSObject::SetProperty(LookupResult* result,
String* name,
Object* value,
- PropertyAttributes attributes) {
+ PropertyAttributes attributes,
+ StrictModeFlag strict) {
Heap* heap = GetHeap();
// Make sure that the top context does not change when doing callbacks or
// interceptor calls.
@@ -1950,7 +1970,8 @@
Object* proto = GetPrototype();
if (proto->IsNull()) return value;
ASSERT(proto->IsJSGlobalObject());
- return JSObject::cast(proto)->SetProperty(result, name, value, attributes);
+ return JSObject::cast(proto)->SetProperty(
+ result, name, value, attributes, strict);
}
if (!result->IsProperty() && !IsJSContextExtensionObject()) {
@@ -1969,7 +1990,19 @@
// Neither properties nor transitions found.
return AddProperty(name, value, attributes);
}
- if (result->IsReadOnly() && result->IsProperty()) return value;
+ if (result->IsReadOnly() && result->IsProperty()) {
+ if (strict == kStrictMode) {
+ HandleScope scope;
+ Handle<String> key(name);
+ Handle<Object> holder(this);
+ Handle<Object> args[2] = { key, holder };
+ return heap->isolate()->Throw(*heap->isolate()->factory()->NewTypeError(
+ "strict_read_only_property", HandleVector(args, 2)));
+
+ } else {
+ return value;
+ }
+ }
// This is a real property that is not read-only, or it is a
// transition or null descriptor and there are no setters in the prototypes.
switch (result->type()) {
@@ -1997,7 +2030,7 @@
value,
result->holder());
case INTERCEPTOR:
- return SetPropertyWithInterceptor(name, value, attributes);
+ return SetPropertyWithInterceptor(name, value, attributes, strict);
case CONSTANT_TRANSITION: {
// If the same constant function is being added we can simply
// transition to the target map.
@@ -2676,7 +2709,18 @@
NumberDictionary* dictionary = element_dictionary();
int entry = dictionary->FindEntry(index);
if (entry != NumberDictionary::kNotFound) {
- return dictionary->DeleteProperty(entry, mode);
+ Object* result = dictionary->DeleteProperty(entry, mode);
+ if (mode == STRICT_DELETION && result ==
+ isolate->heap()->false_value()) {
+ // In strict mode, deleting a non-configurable property throws
+ // exception. dictionary->DeleteProperty will return false_value()
+ // if a non-configurable property is being deleted.
+ HandleScope scope;
+ Handle<Object> i = isolate->factory()->NewNumberFromUint(index);
+ Handle<Object> args[2] = { i, Handle<Object>(this) };
+ return isolate->Throw(*isolate->factory()->NewTypeError(
+ "strict_delete_property", HandleVector(args, 2)));
+ }
}
break;
}
@@ -2716,6 +2760,13 @@
if (!result.IsProperty()) return isolate->heap()->true_value();
// Ignore attributes if forcing a deletion.
if (result.IsDontDelete() && mode != FORCE_DELETION) {
+ if (mode == STRICT_DELETION) {
+ // Deleting a non-configurable property in strict mode.
+ HandleScope scope(isolate);
+ Handle<Object> args[2] = { Handle<Object>(name), Handle<Object>(this) };
+ return isolate->Throw(*isolate->factory()->NewTypeError(
+ "strict_delete_property", HandleVector(args, 2)));
+ }
return isolate->heap()->false_value();
}
// Check for interceptor.
@@ -2840,6 +2891,15 @@
MaybeObject* JSObject::PreventExtensions() {
+ Isolate* isolate = GetIsolate();
+ if (IsAccessCheckNeeded() &&
+ !isolate->MayNamedAccess(this,
+ isolate->heap()->undefined_value(),
+ v8::ACCESS_KEYS)) {
+ isolate->ReportFailedAccessCheck(this, v8::ACCESS_KEYS);
+ return isolate->heap()->false_value();
+ }
+
if (IsJSGlobalProxy()) {
Object* proto = GetPrototype();
if (proto->IsNull()) return this;
@@ -5530,9 +5590,11 @@
bool JSFunction::IsInlineable() {
if (IsBuiltin()) return false;
+ SharedFunctionInfo* shared_info = shared();
// Check that the function has a script associated with it.
- if (!shared()->script()->IsScript()) return false;
- Code* code = shared()->code();
+ if (!shared_info->script()->IsScript()) return false;
+ if (shared_info->optimization_disabled()) return false;
+ Code* code = shared_info->code();
if (code->kind() == Code::OPTIMIZED_FUNCTION) return true;
// If we never ran this (unlikely) then lets try to optimize it.
if (code->kind() != Code::FUNCTION) return true;
@@ -6345,10 +6407,36 @@
}
+void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) {
+ const char* name = NULL;
+ switch (kind) {
+ case CALL_IC:
+ if (extra == STRING_INDEX_OUT_OF_BOUNDS) {
+ name = "STRING_INDEX_OUT_OF_BOUNDS";
+ }
+ break;
+ case STORE_IC:
+ case KEYED_STORE_IC:
+ if (extra == kStrictMode) {
+ name = "STRICT";
+ }
+ break;
+ default:
+ break;
+ }
+ if (name != NULL) {
+ PrintF(out, "extra_ic_state = %s\n", name);
+ } else {
+ PrintF(out, "etra_ic_state = %d\n", extra);
+ }
+}
+
+
void Code::Disassemble(const char* name, FILE* out) {
PrintF(out, "kind = %s\n", Kind2String(kind()));
if (is_inline_cache_stub()) {
PrintF(out, "ic_state = %s\n", ICState2String(ic_state()));
+ PrintExtraICState(out, kind(), extra_ic_state());
PrintF(out, "ic_in_loop = %d\n", ic_in_loop() == IN_LOOP);
if (ic_state() == MONOMORPHIC) {
PrintF(out, "type = %s\n", PropertyType2String(type()));
@@ -6715,7 +6803,6 @@
break;
}
case PIXEL_ELEMENTS: {
- // TODO(iposva): Add testcase.
PixelArray* pixels = PixelArray::cast(elements());
if (index < static_cast<uint32_t>(pixels->length())) {
return true;
@@ -6729,7 +6816,6 @@
case EXTERNAL_INT_ELEMENTS:
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
case EXTERNAL_FLOAT_ELEMENTS: {
- // TODO(kbr): Add testcase.
ExternalArray* array = ExternalArray::cast(elements());
if (index < static_cast<uint32_t>(array->length())) {
return true;
@@ -7319,7 +7405,7 @@
}
-MaybeObject* JSObject::GetElementPostInterceptor(JSObject* receiver,
+MaybeObject* JSObject::GetElementPostInterceptor(Object* receiver,
uint32_t index) {
Heap* heap = GetHeap();
// Get element works for both JSObject and JSArray since
@@ -7333,11 +7419,7 @@
}
break;
}
- case PIXEL_ELEMENTS: {
- // TODO(iposva): Add testcase and implement.
- UNIMPLEMENTED();
- break;
- }
+ case PIXEL_ELEMENTS:
case EXTERNAL_BYTE_ELEMENTS:
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
case EXTERNAL_SHORT_ELEMENTS:
@@ -7345,8 +7427,10 @@
case EXTERNAL_INT_ELEMENTS:
case EXTERNAL_UNSIGNED_INT_ELEMENTS:
case EXTERNAL_FLOAT_ELEMENTS: {
- // TODO(kbr): Add testcase and implement.
- UNIMPLEMENTED();
+ MaybeObject* maybe_value = GetExternalElement(index);
+ Object* value;
+ if (!maybe_value->ToObject(&value)) return maybe_value;
+ if (!value->IsUndefined()) return value;
break;
}
case DICTIONARY_ELEMENTS: {
@@ -7377,7 +7461,7 @@
}
-MaybeObject* JSObject::GetElementWithInterceptor(JSObject* receiver,
+MaybeObject* JSObject::GetElementWithInterceptor(Object* receiver,
uint32_t index) {
Isolate* isolate = GetIsolate();
// Make sure that the top context does not change when doing
@@ -7385,7 +7469,7 @@
AssertNoContextChange ncc;
HandleScope scope(isolate);
Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
- Handle<JSObject> this_handle(receiver);
+ Handle<Object> this_handle(receiver);
Handle<JSObject> holder_handle(this);
if (!interceptor->getter()->IsUndefined()) {
@@ -7411,7 +7495,7 @@
}
-MaybeObject* JSObject::GetElementWithReceiver(JSObject* receiver,
+MaybeObject* JSObject::GetElementWithReceiver(Object* receiver,
uint32_t index) {
Heap* heap = GetHeap();
// Check access rights if needed.
@@ -7436,6 +7520,48 @@
}
break;
}
+ case PIXEL_ELEMENTS:
+ case EXTERNAL_BYTE_ELEMENTS:
+ case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
+ case EXTERNAL_SHORT_ELEMENTS:
+ case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
+ case EXTERNAL_INT_ELEMENTS:
+ case EXTERNAL_UNSIGNED_INT_ELEMENTS:
+ case EXTERNAL_FLOAT_ELEMENTS: {
+ MaybeObject* maybe_value = GetExternalElement(index);
+ Object* value;
+ if (!maybe_value->ToObject(&value)) return maybe_value;
+ if (!value->IsUndefined()) return value;
+ break;
+ }
+ case DICTIONARY_ELEMENTS: {
+ NumberDictionary* dictionary = element_dictionary();
+ int entry = dictionary->FindEntry(index);
+ if (entry != NumberDictionary::kNotFound) {
+ Object* element = dictionary->ValueAt(entry);
+ PropertyDetails details = dictionary->DetailsAt(entry);
+ if (details.type() == CALLBACKS) {
+ return GetElementWithCallback(receiver,
+ element,
+ index,
+ this);
+ }
+ return element;
+ }
+ break;
+ }
+ }
+
+ Object* pt = GetPrototype();
+ if (pt == heap->null_value()) return heap->undefined_value();
+ return pt->GetElementWithReceiver(receiver, index);
+}
+
+
+MaybeObject* JSObject::GetExternalElement(uint32_t index) {
+ // Get element works for both JSObject and JSArray since
+ // JSArray::length cannot change.
+ switch (GetElementsKind()) {
case PIXEL_ELEMENTS: {
PixelArray* pixels = PixelArray::cast(elements());
if (index < static_cast<uint32_t>(pixels->length())) {
@@ -7482,7 +7608,7 @@
ExternalIntArray* array = ExternalIntArray::cast(elements());
if (index < static_cast<uint32_t>(array->length())) {
int32_t value = array->get(index);
- return heap->NumberFromInt32(value);
+ return GetHeap()->NumberFromInt32(value);
}
break;
}
@@ -7491,7 +7617,7 @@
ExternalUnsignedIntArray::cast(elements());
if (index < static_cast<uint32_t>(array->length())) {
uint32_t value = array->get(index);
- return heap->NumberFromUint32(value);
+ return GetHeap()->NumberFromUint32(value);
}
break;
}
@@ -7499,31 +7625,16 @@
ExternalFloatArray* array = ExternalFloatArray::cast(elements());
if (index < static_cast<uint32_t>(array->length())) {
float value = array->get(index);
- return heap->AllocateHeapNumber(value);
+ return GetHeap()->AllocateHeapNumber(value);
}
break;
}
- case DICTIONARY_ELEMENTS: {
- NumberDictionary* dictionary = element_dictionary();
- int entry = dictionary->FindEntry(index);
- if (entry != NumberDictionary::kNotFound) {
- Object* element = dictionary->ValueAt(entry);
- PropertyDetails details = dictionary->DetailsAt(entry);
- if (details.type() == CALLBACKS) {
- return GetElementWithCallback(receiver,
- element,
- index,
- this);
- }
- return element;
- }
+ case FAST_ELEMENTS:
+ case DICTIONARY_ELEMENTS:
+ UNREACHABLE();
break;
- }
}
-
- Object* pt = GetPrototype();
- if (pt->IsNull()) return heap->undefined_value();
- return pt->GetElementWithReceiver(receiver, index);
+ return GetHeap()->undefined_value();
}
@@ -8641,10 +8752,20 @@
if (value->IsUndefined()) {
undefs++;
} else {
+ if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
+ // Adding an entry with the key beyond smi-range requires
+ // allocation. Bailout.
+ return Smi::FromInt(-1);
+ }
new_dict->AddNumberEntry(pos, value, details)->ToObjectUnchecked();
pos++;
}
} else {
+ if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
+ // Adding an entry with the key beyond smi-range requires
+ // allocation. Bailout.
+ return Smi::FromInt(-1);
+ }
new_dict->AddNumberEntry(key, value, details)->ToObjectUnchecked();
}
}
@@ -8653,6 +8774,11 @@
uint32_t result = pos;
PropertyDetails no_details = PropertyDetails(NONE, NORMAL);
while (undefs > 0) {
+ if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
+ // Adding an entry with the key beyond smi-range requires
+ // allocation. Bailout.
+ return Smi::FromInt(-1);
+ }
new_dict->AddNumberEntry(pos, heap->undefined_value(), no_details)->
ToObjectUnchecked();
pos++;
@@ -9393,7 +9519,7 @@
Heap* heap = Dictionary<Shape, Key>::GetHeap();
PropertyDetails details = DetailsAt(entry);
// Ignore attributes if forcing a deletion.
- if (details.IsDontDelete() && mode == JSObject::NORMAL_DELETION) {
+ if (details.IsDontDelete() && mode != JSObject::FORCE_DELETION) {
return heap->false_value();
}
SetEntry(entry, heap->null_value(), heap->null_value(), Smi::FromInt(0));
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698