Version 3.1.3.
Fixed a bug triggered by functions with huge numbers of declared arguments.
Fixed zap value aliasing a real object - debug mode only. Issue 866.
Fixed issue where Array.prototype.__proto__ had been set to null. Issue 1121.
Fixed stability bugs in Crankshaft for x86.
Review URL: http://codereview.chromium.org/6460038
git-svn-id: http://v8.googlecode.com/svn/trunk@6711 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/runtime.cc b/src/runtime.cc
index 4994378..5fdd6fb 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -884,10 +884,17 @@
return obj->PreventExtensions();
}
+
static MaybeObject* Runtime_IsExtensible(Arguments args) {
ASSERT(args.length() == 1);
CONVERT_CHECKED(JSObject, obj, args[0]);
- return obj->map()->is_extensible() ? Heap::true_value()
+ if (obj->IsJSGlobalProxy()) {
+ Object* proto = obj->GetPrototype();
+ if (proto->IsNull()) return Heap::false_value();
+ ASSERT(proto->IsJSGlobalObject());
+ obj = JSObject::cast(proto);
+ }
+ return obj->map()->is_extensible() ? Heap::true_value()
: Heap::false_value();
}
@@ -1082,7 +1089,11 @@
const char* type = (lookup.IsReadOnly()) ? "const" : "var";
return ThrowRedeclarationError(type, name);
}
- SetProperty(global, name, value, attributes);
+ Handle<Object> result = SetProperty(global, name, value, attributes);
+ if (result.is_null()) {
+ ASSERT(Top::has_pending_exception());
+ return Failure::Exception();
+ }
} else {
// If a property with this name does not already exist on the
// global object add the property locally. We take special
@@ -1090,10 +1101,16 @@
// of callbacks in the prototype chain (this rules out using
// SetProperty). Also, we must use the handle-based version to
// avoid GC issues.
- SetLocalPropertyIgnoreAttributes(global, name, value, attributes);
+ Handle<Object> result =
+ SetLocalPropertyIgnoreAttributes(global, name, value, attributes);
+ if (result.is_null()) {
+ ASSERT(Top::has_pending_exception());
+ return Failure::Exception();
+ }
}
}
+ ASSERT(!Top::has_pending_exception());
return Heap::undefined_value();
}
@@ -1143,12 +1160,15 @@
} else {
// The holder is an arguments object.
Handle<JSObject> arguments(Handle<JSObject>::cast(holder));
- SetElement(arguments, index, initial_value);
+ Handle<Object> result = SetElement(arguments, index, initial_value);
+ if (result.is_null()) return Failure::Exception();
}
} else {
// Slow case: The property is not in the FixedArray part of the context.
Handle<JSObject> context_ext = Handle<JSObject>::cast(holder);
- SetProperty(context_ext, name, initial_value, mode);
+ Handle<Object> result =
+ SetProperty(context_ext, name, initial_value, mode);
+ if (result.is_null()) return Failure::Exception();
}
}
@@ -1175,8 +1195,8 @@
ASSERT(!context_ext->HasLocalProperty(*name));
Handle<Object> value(Heap::undefined_value());
if (*initial_value != NULL) value = initial_value;
- SetProperty(context_ext, name, value, mode);
- ASSERT(context_ext->GetLocalPropertyAttribute(*name) == mode);
+ Handle<Object> result = SetProperty(context_ext, name, value, mode);
+ if (result.is_null()) return Failure::Exception();
}
return Heap::undefined_value();
@@ -3668,14 +3688,20 @@
if (((unchecked & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) &&
is_element) {
// Normalize the elements to enable attributes on the property.
- if (!js_object->IsJSGlobalProxy()) {
- NormalizeElements(js_object);
+ if (js_object->IsJSGlobalProxy()) {
+ Handle<Object> proto(js_object->GetPrototype());
+ // If proxy is detached, ignore the assignment. Alternatively,
+ // we could throw an exception.
+ if (proto->IsNull()) return *obj_value;
+ js_object = Handle<JSObject>::cast(proto);
}
+ NormalizeElements(js_object);
Handle<NumberDictionary> dictionary(js_object->element_dictionary());
// Make sure that we never go back to fast case.
dictionary->set_requires_slow_elements();
PropertyDetails details = PropertyDetails(attr, NORMAL);
NumberDictionarySet(dictionary, index, obj_value, details);
+ return *obj_value;
}
LookupResult result;
@@ -3690,9 +3716,12 @@
if (result.IsProperty() &&
(attr != result.GetAttributes() || result.type() == CALLBACKS)) {
// New attributes - normalize to avoid writing to instance descriptor
- if (!js_object->IsJSGlobalProxy()) {
- NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0);
+ if (js_object->IsJSGlobalProxy()) {
+ // Since the result is a property, the prototype will exist so
+ // we don't have to check for null.
+ js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype()));
}
+ NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0);
// Use IgnoreAttributes version since a readonly property may be
// overridden and SetProperty does not allow this.
return js_object->SetLocalPropertyIgnoreAttributes(*name,
@@ -6681,28 +6710,50 @@
return *result;
}
+
static MaybeObject* Runtime_NewObjectFromBound(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 2);
+ // First argument is a function to use as a constructor.
CONVERT_ARG_CHECKED(JSFunction, function, 0);
- CONVERT_ARG_CHECKED(JSArray, params, 1);
- RUNTIME_ASSERT(params->HasFastElements());
- FixedArray* fixed = FixedArray::cast(params->elements());
+ // Second argument is either null or an array of bound arguments.
+ FixedArray* bound_args = NULL;
+ int bound_argc = 0;
+ if (!args[1]->IsNull()) {
+ CONVERT_ARG_CHECKED(JSArray, params, 1);
+ RUNTIME_ASSERT(params->HasFastElements());
+ bound_args = FixedArray::cast(params->elements());
+ bound_argc = Smi::cast(params->length())->value();
+ }
- int fixed_length = Smi::cast(params->length())->value();
- SmartPointer<Object**> param_data(NewArray<Object**>(fixed_length));
- for (int i = 0; i < fixed_length; i++) {
- Handle<Object> val = Handle<Object>(fixed->get(i));
+ // Find frame containing arguments passed to the caller.
+ JavaScriptFrameIterator it;
+ JavaScriptFrame* frame = it.frame();
+ ASSERT(!frame->is_optimized());
+ it.AdvanceToArgumentsFrame();
+ frame = it.frame();
+ int argc = frame->GetProvidedParametersCount();
+
+ // Prepend bound arguments to caller's arguments.
+ int total_argc = bound_argc + argc;
+ SmartPointer<Object**> param_data(NewArray<Object**>(total_argc));
+ for (int i = 0; i < bound_argc; i++) {
+ Handle<Object> val = Handle<Object>(bound_args->get(i));
param_data[i] = val.location();
}
+ for (int i = 0; i < argc; i++) {
+ Handle<Object> val = Handle<Object>(frame->GetParameter(i));
+ param_data[bound_argc + i] = val.location();
+ }
bool exception = false;
- Handle<Object> result = Execution::New(
- function, fixed_length, *param_data, &exception);
+ Handle<Object> result =
+ Execution::New(function, total_argc, *param_data, &exception);
if (exception) {
return Failure::Exception();
}
+
ASSERT(!result.is_null());
return *result;
}
@@ -7340,12 +7391,17 @@
if (holder->IsContext()) {
// Ignore if read_only variable.
if ((attributes & READ_ONLY) == 0) {
- Handle<Context>::cast(holder)->set(index, *value);
+ // Context is a fixed array and set cannot fail.
+ Context::cast(*holder)->set(index, *value);
}
} else {
ASSERT((attributes & READ_ONLY) == 0);
- Handle<JSObject>::cast(holder)->SetElement(index, *value)->
- ToObjectUnchecked();
+ Handle<Object> result =
+ SetElement(Handle<JSObject>::cast(holder), index, value);
+ if (result.is_null()) {
+ ASSERT(Top::has_pending_exception());
+ return Failure::Exception();
+ }
}
return *value;
}
@@ -7368,8 +7424,8 @@
// extension object itself.
if ((attributes & READ_ONLY) == 0 ||
(context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) {
- Handle<Object> set = SetProperty(context_ext, name, value, NONE);
- if (set.is_null()) {
+ Handle<Object> result = SetProperty(context_ext, name, value, NONE);
+ if (result.is_null()) {
// Failure::Exception is converted to a null handle in the
// handle-based methods such as SetProperty. We therefore need
// to convert null handles back to exceptions.