| Index: src/runtime.cc
|
| ===================================================================
|
| --- src/runtime.cc (revision 8778)
|
| +++ src/runtime.cc (working copy)
|
| @@ -219,9 +219,21 @@
|
| }
|
| break;
|
| }
|
| - default:
|
| - UNREACHABLE();
|
| + case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
|
| + UNIMPLEMENTED();
|
| break;
|
| + case JSObject::EXTERNAL_PIXEL_ELEMENTS:
|
| + case JSObject::EXTERNAL_BYTE_ELEMENTS:
|
| + case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
| + case JSObject::EXTERNAL_SHORT_ELEMENTS:
|
| + case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
| + case JSObject::EXTERNAL_INT_ELEMENTS:
|
| + case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
| + case JSObject::EXTERNAL_FLOAT_ELEMENTS:
|
| + case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
|
| + case JSObject::FAST_DOUBLE_ELEMENTS:
|
| + // No contained objects, nothing to do.
|
| + break;
|
| }
|
| return copy;
|
| }
|
| @@ -615,6 +627,14 @@
|
| }
|
|
|
|
|
| +RUNTIME_FUNCTION(MaybeObject*, Runtime_Fix) {
|
| + ASSERT(args.length() == 1);
|
| + CONVERT_CHECKED(JSProxy, proxy, args[0]);
|
| + proxy->Fix();
|
| + return isolate->heap()->undefined_value();
|
| +}
|
| +
|
| +
|
| RUNTIME_FUNCTION(MaybeObject*, Runtime_ClassOf) {
|
| NoHandleAllocation ha;
|
| ASSERT(args.length() == 1);
|
| @@ -1152,7 +1172,7 @@
|
| return ThrowRedeclarationError(isolate, "const", name);
|
| }
|
| // Otherwise, we check for locally conflicting declarations.
|
| - if (is_local && (is_read_only || is_const_property)) {
|
| + if (is_local && is_const_property) {
|
| const char* type = (is_read_only) ? "const" : "var";
|
| return ThrowRedeclarationError(isolate, type, name);
|
| }
|
| @@ -1386,12 +1406,11 @@
|
| // make sure to introduce it.
|
| found = false;
|
| } else if ((intercepted & READ_ONLY) != 0) {
|
| - // The property is present, but read-only. Since we're trying to
|
| - // overwrite it with a variable declaration we must throw a
|
| - // re-declaration error. However if we found readonly property
|
| + // The property is present, but read-only, so we ignore the
|
| + // redeclaration. However if we found readonly property
|
| // on one of hidden prototypes, just shadow it.
|
| if (real_holder != isolate->context()->global()) break;
|
| - return ThrowRedeclarationError(isolate, "const", name);
|
| + return isolate->heap()->undefined_value();
|
| }
|
| }
|
|
|
| @@ -1658,7 +1677,9 @@
|
| RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpConstructResult) {
|
| ASSERT(args.length() == 3);
|
| CONVERT_SMI_ARG_CHECKED(elements_count, 0);
|
| - if (elements_count > JSArray::kMaxFastElementsLength) {
|
| + if (elements_count < 0 ||
|
| + elements_count > FixedArray::kMaxLength ||
|
| + !Smi::IsValid(elements_count)) {
|
| return isolate->ThrowIllegalOperation();
|
| }
|
| Object* new_object;
|
| @@ -1960,6 +1981,61 @@
|
| }
|
|
|
|
|
| +RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetReadOnlyPrototype) {
|
| + NoHandleAllocation ha;
|
| + RUNTIME_ASSERT(args.length() == 1);
|
| + CONVERT_CHECKED(JSFunction, function, args[0]);
|
| +
|
| + MaybeObject* maybe_name =
|
| + isolate->heap()->AllocateStringFromAscii(CStrVector("prototype"));
|
| + String* name;
|
| + if (!maybe_name->To(&name)) return maybe_name;
|
| +
|
| + if (function->HasFastProperties()) {
|
| + // Construct a new field descriptor with updated attributes.
|
| + DescriptorArray* instance_desc = function->map()->instance_descriptors();
|
| + int index = instance_desc->Search(name);
|
| + ASSERT(index != DescriptorArray::kNotFound);
|
| + PropertyDetails details(instance_desc->GetDetails(index));
|
| + CallbacksDescriptor new_desc(name,
|
| + instance_desc->GetValue(index),
|
| + static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
|
| + details.index());
|
| + // Construct a new field descriptors array containing the new descriptor.
|
| + Object* descriptors_unchecked;
|
| + { MaybeObject* maybe_descriptors_unchecked =
|
| + instance_desc->CopyInsert(&new_desc, REMOVE_TRANSITIONS);
|
| + if (!maybe_descriptors_unchecked->ToObject(&descriptors_unchecked)) {
|
| + return maybe_descriptors_unchecked;
|
| + }
|
| + }
|
| + DescriptorArray* new_descriptors =
|
| + DescriptorArray::cast(descriptors_unchecked);
|
| + // Create a new map featuring the new field descriptors array.
|
| + Object* map_unchecked;
|
| + { MaybeObject* maybe_map_unchecked = function->map()->CopyDropDescriptors();
|
| + if (!maybe_map_unchecked->ToObject(&map_unchecked)) {
|
| + return maybe_map_unchecked;
|
| + }
|
| + }
|
| + Map* new_map = Map::cast(map_unchecked);
|
| + new_map->set_instance_descriptors(new_descriptors);
|
| + function->set_map(new_map);
|
| + } else { // Dictionary properties.
|
| + // Directly manipulate the property details.
|
| + int entry = function->property_dictionary()->FindEntry(name);
|
| + ASSERT(entry != StringDictionary::kNotFound);
|
| + PropertyDetails details = function->property_dictionary()->DetailsAt(entry);
|
| + PropertyDetails new_details(
|
| + static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
|
| + details.type(),
|
| + details.index());
|
| + function->property_dictionary()->DetailsAtPut(entry, new_details);
|
| + }
|
| + return function;
|
| +}
|
| +
|
| +
|
| RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsAPIFunction) {
|
| NoHandleAllocation ha;
|
| ASSERT(args.length() == 1);
|
| @@ -3875,7 +3951,7 @@
|
| || result.type() == CONSTANT_FUNCTION)) {
|
| Object* ok;
|
| { MaybeObject* maybe_ok =
|
| - obj->DeleteProperty(name, JSObject::NORMAL_DELETION);
|
| + obj->DeleteProperty(name, JSReceiver::NORMAL_DELETION);
|
| if (!maybe_ok->ToObject(&ok)) return maybe_ok;
|
| }
|
| }
|
| @@ -4129,24 +4205,25 @@
|
|
|
|
|
| MaybeObject* Runtime::ForceDeleteObjectProperty(Isolate* isolate,
|
| - Handle<JSObject> js_object,
|
| + Handle<JSReceiver> receiver,
|
| Handle<Object> key) {
|
| HandleScope scope(isolate);
|
|
|
| // Check if the given key is an array index.
|
| uint32_t index;
|
| - if (key->ToArrayIndex(&index)) {
|
| + if (receiver->IsJSObject() && key->ToArrayIndex(&index)) {
|
| // In Firefox/SpiderMonkey, Safari and Opera you can access the
|
| // characters of a string using [] notation. In the case of a
|
| // String object we just need to redirect the deletion to the
|
| // underlying string if the index is in range. Since the
|
| // underlying string does nothing with the deletion, we can ignore
|
| // such deletions.
|
| - if (js_object->IsStringObjectWithCharacterAt(index)) {
|
| + if (receiver->IsStringObjectWithCharacterAt(index)) {
|
| return isolate->heap()->true_value();
|
| }
|
|
|
| - return js_object->DeleteElement(index, JSObject::FORCE_DELETION);
|
| + return JSObject::cast(*receiver)->DeleteElement(
|
| + index, JSReceiver::FORCE_DELETION);
|
| }
|
|
|
| Handle<String> key_string;
|
| @@ -4161,7 +4238,7 @@
|
| }
|
|
|
| key_string->TryFlatten();
|
| - return js_object->DeleteProperty(*key_string, JSObject::FORCE_DELETION);
|
| + return receiver->DeleteProperty(*key_string, JSReceiver::FORCE_DELETION);
|
| }
|
|
|
|
|
| @@ -4240,12 +4317,12 @@
|
| NoHandleAllocation ha;
|
| ASSERT(args.length() == 3);
|
|
|
| - CONVERT_CHECKED(JSObject, object, args[0]);
|
| + CONVERT_CHECKED(JSReceiver, object, args[0]);
|
| CONVERT_CHECKED(String, key, args[1]);
|
| CONVERT_SMI_ARG_CHECKED(strict, 2);
|
| return object->DeleteProperty(key, (strict == kStrictMode)
|
| - ? JSObject::STRICT_DELETION
|
| - : JSObject::NORMAL_DELETION);
|
| + ? JSReceiver::STRICT_DELETION
|
| + : JSReceiver::NORMAL_DELETION);
|
| }
|
|
|
|
|
| @@ -4309,11 +4386,11 @@
|
| NoHandleAllocation na;
|
| ASSERT(args.length() == 2);
|
|
|
| - // Only JS objects can have properties.
|
| - if (args[0]->IsJSObject()) {
|
| - JSObject* object = JSObject::cast(args[0]);
|
| + // Only JS receivers can have properties.
|
| + if (args[0]->IsJSReceiver()) {
|
| + JSReceiver* receiver = JSReceiver::cast(args[0]);
|
| CONVERT_CHECKED(String, key, args[1]);
|
| - if (object->HasProperty(key)) return isolate->heap()->true_value();
|
| + if (receiver->HasProperty(key)) return isolate->heap()->true_value();
|
| }
|
| return isolate->heap()->false_value();
|
| }
|
| @@ -4457,7 +4534,7 @@
|
| for (int i = 0; i < length; i++) {
|
| jsproto->GetLocalPropertyNames(*names,
|
| i == 0 ? 0 : local_property_count[i - 1]);
|
| - if (!GetHiddenProperties(jsproto, false)->IsUndefined()) {
|
| + if (jsproto->HasHiddenProperties()) {
|
| proto_with_hidden_properties++;
|
| }
|
| if (i < length - 1) {
|
| @@ -8201,9 +8278,9 @@
|
| // index is non-negative.
|
| Handle<JSObject> object = Handle<JSObject>::cast(holder);
|
| if (index >= 0) {
|
| - return object->DeleteElement(index, JSObject::NORMAL_DELETION);
|
| + return object->DeleteElement(index, JSReceiver::NORMAL_DELETION);
|
| } else {
|
| - return object->DeleteProperty(*name, JSObject::NORMAL_DELETION);
|
| + return object->DeleteProperty(*name, JSReceiver::NORMAL_DELETION);
|
| }
|
| }
|
|
|
| @@ -9515,6 +9592,9 @@
|
| if (new_elements->map() == isolate->heap()->fixed_array_map() ||
|
| new_elements->map() == isolate->heap()->fixed_cow_array_map()) {
|
| maybe_new_map = to->map()->GetFastElementsMap();
|
| + } else if (new_elements->map() ==
|
| + isolate->heap()->fixed_double_array_map()) {
|
| + maybe_new_map = to->map()->GetFastDoubleElementsMap();
|
| } else {
|
| maybe_new_map = to->map()->GetSlowElementsMap();
|
| }
|
| @@ -9602,12 +9682,13 @@
|
| }
|
| return *isolate->factory()->NewJSArrayWithElements(keys);
|
| } else {
|
| - ASSERT(array->HasFastElements());
|
| + ASSERT(array->HasFastElements() || array->HasFastDoubleElements());
|
| Handle<FixedArray> single_interval = isolate->factory()->NewFixedArray(2);
|
| // -1 means start of array.
|
| single_interval->set(0, Smi::FromInt(-1));
|
| + FixedArrayBase* elements = FixedArrayBase::cast(array->elements());
|
| uint32_t actual_length =
|
| - static_cast<uint32_t>(FixedArray::cast(array->elements())->length());
|
| + static_cast<uint32_t>(elements->length());
|
| uint32_t min_length = actual_length < length ? actual_length : length;
|
| Handle<Object> length_object =
|
| isolate->factory()->NewNumber(static_cast<double>(min_length));
|
| @@ -9979,6 +10060,71 @@
|
| }
|
|
|
|
|
| +class FrameInspector {
|
| + public:
|
| + FrameInspector(JavaScriptFrame* frame,
|
| + int inlined_frame_index,
|
| + Isolate* isolate)
|
| + : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) {
|
| + // Calculate the deoptimized frame.
|
| + if (frame->is_optimized()) {
|
| + deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame(
|
| + frame, inlined_frame_index, isolate);
|
| + }
|
| + has_adapted_arguments_ = frame_->has_adapted_arguments();
|
| + is_optimized_ = frame_->is_optimized();
|
| + }
|
| +
|
| + ~FrameInspector() {
|
| + // Get rid of the calculated deoptimized frame if any.
|
| + if (deoptimized_frame_ != NULL) {
|
| + Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_,
|
| + isolate_);
|
| + }
|
| + }
|
| +
|
| + int GetParametersCount() {
|
| + return is_optimized_
|
| + ? deoptimized_frame_->parameters_count()
|
| + : frame_->ComputeParametersCount();
|
| + }
|
| + int expression_count() { return deoptimized_frame_->expression_count(); }
|
| + Object* GetFunction() {
|
| + return is_optimized_
|
| + ? deoptimized_frame_->GetFunction()
|
| + : frame_->function();
|
| + }
|
| + Object* GetParameter(int index) {
|
| + return is_optimized_
|
| + ? deoptimized_frame_->GetParameter(index)
|
| + : frame_->GetParameter(index);
|
| + }
|
| + Object* GetExpression(int index) {
|
| + return is_optimized_
|
| + ? deoptimized_frame_->GetExpression(index)
|
| + : frame_->GetExpression(index);
|
| + }
|
| +
|
| + // To inspect all the provided arguments the frame might need to be
|
| + // replaced with the arguments frame.
|
| + void SetArgumentsFrame(JavaScriptFrame* frame) {
|
| + ASSERT(has_adapted_arguments_);
|
| + frame_ = frame;
|
| + is_optimized_ = frame_->is_optimized();
|
| + ASSERT(!is_optimized_);
|
| + }
|
| +
|
| + private:
|
| + JavaScriptFrame* frame_;
|
| + DeoptimizedFrameInfo* deoptimized_frame_;
|
| + Isolate* isolate_;
|
| + bool is_optimized_;
|
| + bool has_adapted_arguments_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(FrameInspector);
|
| +};
|
| +
|
| +
|
| static const int kFrameDetailsFrameIdIndex = 0;
|
| static const int kFrameDetailsReceiverIndex = 1;
|
| static const int kFrameDetailsFunctionIndex = 2;
|
| @@ -10027,8 +10173,7 @@
|
| return heap->undefined_value();
|
| }
|
|
|
| - int deoptimized_frame_index = -1; // Frame index in optimized frame.
|
| - DeoptimizedFrameInfo* deoptimized_frame = NULL;
|
| + int inlined_frame_index = 0; // Inlined frame index in optimized frame.
|
|
|
| int count = 0;
|
| JavaScriptFrameIterator it(isolate, id);
|
| @@ -10039,13 +10184,10 @@
|
| if (it.done()) return heap->undefined_value();
|
|
|
| if (it.frame()->is_optimized()) {
|
| - deoptimized_frame_index =
|
| + inlined_frame_index =
|
| it.frame()->GetInlineCount() - (index - count) - 1;
|
| - deoptimized_frame = Deoptimizer::DebuggerInspectableFrame(
|
| - it.frame(),
|
| - deoptimized_frame_index,
|
| - isolate);
|
| }
|
| + FrameInspector frame_inspector(it.frame(), inlined_frame_index, isolate);
|
|
|
| // Traverse the saved contexts chain to find the active context for the
|
| // selected frame.
|
| @@ -10064,12 +10206,13 @@
|
|
|
| // Check for constructor frame. Inlined frames cannot be construct calls.
|
| bool inlined_frame =
|
| - it.frame()->is_optimized() && deoptimized_frame_index != 0;
|
| + it.frame()->is_optimized() && inlined_frame_index != 0;
|
| bool constructor = !inlined_frame && it.frame()->IsConstructor();
|
|
|
| // Get scope info and read from it for local variable information.
|
| Handle<JSFunction> function(JSFunction::cast(it.frame()->function()));
|
| - Handle<SerializedScopeInfo> scope_info(function->shared()->scope_info());
|
| + Handle<SharedFunctionInfo> shared(function->shared());
|
| + Handle<SerializedScopeInfo> scope_info(shared->scope_info());
|
| ASSERT(*scope_info != SerializedScopeInfo::Empty());
|
| ScopeInfo<> info(*scope_info);
|
|
|
| @@ -10086,14 +10229,7 @@
|
| for (; i < info.number_of_stack_slots(); ++i) {
|
| // Use the value from the stack.
|
| locals->set(i * 2, *info.LocalName(i));
|
| - if (it.frame()->is_optimized()) {
|
| - // Get the value from the deoptimized frame.
|
| - locals->set(i * 2 + 1,
|
| - deoptimized_frame->GetExpression(i));
|
| - } else {
|
| - // Get the value from the stack.
|
| - locals->set(i * 2 + 1, it.frame()->GetExpression(i));
|
| - }
|
| + locals->set(i * 2 + 1, frame_inspector.GetExpression(i));
|
| }
|
| if (i < info.NumberOfLocals()) {
|
| // Get the context containing declarations.
|
| @@ -10150,18 +10286,22 @@
|
| // the provided parameters whereas the function frame always have the number
|
| // of arguments matching the functions parameters. The rest of the
|
| // information (except for what is collected above) is the same.
|
| - it.AdvanceToArgumentsFrame();
|
| + if (it.frame()->has_adapted_arguments()) {
|
| + it.AdvanceToArgumentsFrame();
|
| + frame_inspector.SetArgumentsFrame(it.frame());
|
| + }
|
|
|
| // Find the number of arguments to fill. At least fill the number of
|
| // parameters for the function and fill more if more parameters are provided.
|
| int argument_count = info.number_of_parameters();
|
| + if (argument_count < frame_inspector.GetParametersCount()) {
|
| + argument_count = frame_inspector.GetParametersCount();
|
| + }
|
| +#ifdef DEBUG
|
| if (it.frame()->is_optimized()) {
|
| - ASSERT_EQ(argument_count, deoptimized_frame->parameters_count());
|
| - } else {
|
| - if (argument_count < it.frame()->ComputeParametersCount()) {
|
| - argument_count = it.frame()->ComputeParametersCount();
|
| - }
|
| + ASSERT_EQ(argument_count, frame_inspector.GetParametersCount());
|
| }
|
| +#endif
|
|
|
| // Calculate the size of the result.
|
| int details_size = kFrameDetailsFirstDynamicIndex +
|
| @@ -10173,13 +10313,7 @@
|
| details->set(kFrameDetailsFrameIdIndex, *frame_id);
|
|
|
| // Add the function (same as in function frame).
|
| - if (it.frame()->is_optimized()) {
|
| - // Get the function from the deoptimized frame.
|
| - details->set(kFrameDetailsFunctionIndex, deoptimized_frame->GetFunction());
|
| - } else {
|
| - // Get the function from the stack.
|
| - details->set(kFrameDetailsFunctionIndex, it.frame()->function());
|
| - }
|
| + details->set(kFrameDetailsFunctionIndex, frame_inspector.GetFunction());
|
|
|
| // Add the arguments count.
|
| details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
|
| @@ -10211,9 +10345,7 @@
|
| }
|
| if (it.frame()->is_optimized()) {
|
| flags |= 1 << 1;
|
| - if (deoptimized_frame_index > 0) {
|
| - flags |= 1 << 2;
|
| - }
|
| + flags |= inlined_frame_index << 2;
|
| }
|
| details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
|
|
|
| @@ -10230,16 +10362,11 @@
|
| }
|
|
|
| // Parameter value.
|
| - if (it.frame()->is_optimized()) {
|
| - // Get the value from the deoptimized frame.
|
| - details->set(details_index++, deoptimized_frame->GetParameter(i));
|
| + if (i < it.frame()->ComputeParametersCount()) {
|
| + // Get the value from the stack.
|
| + details->set(details_index++, frame_inspector.GetParameter(i));
|
| } else {
|
| - if (i < it.frame()->ComputeParametersCount()) {
|
| - // Get the value from the stack.
|
| - details->set(details_index++, it.frame()->GetParameter(i));
|
| - } else {
|
| - details->set(details_index++, heap->undefined_value());
|
| - }
|
| + details->set(details_index++, heap->undefined_value());
|
| }
|
| }
|
|
|
| @@ -10257,10 +10384,11 @@
|
| // THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
|
| // THE FRAME ITERATOR TO WRAP THE RECEIVER.
|
| Handle<Object> receiver(it.frame()->receiver(), isolate);
|
| - if (!receiver->IsJSObject()) {
|
| - // If the receiver is NOT a JSObject we have hit an optimization
|
| - // where a value object is not converted into a wrapped JS objects.
|
| - // To hide this optimization from the debugger, we wrap the receiver
|
| + if (!receiver->IsJSObject() && !shared->strict_mode() && !shared->native()) {
|
| + // If the receiver is not a JSObject and the function is not a
|
| + // builtin or strict-mode we have hit an optimization where a
|
| + // value object is not converted into a wrapped JS objects. To
|
| + // hide this optimization from the debugger, we wrap the receiver
|
| // by creating correct wrapper object based on the calling frame's
|
| // global context.
|
| it.Advance();
|
| @@ -10271,12 +10399,6 @@
|
| }
|
| details->set(kFrameDetailsReceiverIndex, *receiver);
|
|
|
| - // Get rid of the calculated deoptimized frame if any.
|
| - if (deoptimized_frame != NULL) {
|
| - Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame,
|
| - isolate);
|
| - }
|
| -
|
| ASSERT_EQ(details_size, details_index);
|
| return *isolate->factory()->NewJSArrayWithElements(details);
|
| }
|
| @@ -10312,12 +10434,15 @@
|
|
|
| // Create a plain JSObject which materializes the local scope for the specified
|
| // frame.
|
| -static Handle<JSObject> MaterializeLocalScope(Isolate* isolate,
|
| - JavaScriptFrame* frame) {
|
| +static Handle<JSObject> MaterializeLocalScope(
|
| + Isolate* isolate,
|
| + JavaScriptFrame* frame,
|
| + int inlined_frame_index) {
|
| Handle<JSFunction> function(JSFunction::cast(frame->function()));
|
| Handle<SharedFunctionInfo> shared(function->shared());
|
| Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info());
|
| ScopeInfo<> scope_info(*serialized_scope_info);
|
| + FrameInspector frame_inspector(frame, inlined_frame_index, isolate);
|
|
|
| // Allocate and initialize a JSObject with all the arguments, stack locals
|
| // heap locals and extension properties of the debugged function.
|
| @@ -10330,7 +10455,7 @@
|
| isolate,
|
| SetProperty(local_scope,
|
| scope_info.parameter_name(i),
|
| - Handle<Object>(frame->GetParameter(i), isolate),
|
| + Handle<Object>(frame_inspector.GetParameter(i)),
|
| NONE,
|
| kNonStrictMode),
|
| Handle<JSObject>());
|
| @@ -10342,7 +10467,7 @@
|
| isolate,
|
| SetProperty(local_scope,
|
| scope_info.stack_slot_name(i),
|
| - Handle<Object>(frame->GetExpression(i), isolate),
|
| + Handle<Object>(frame_inspector.GetExpression(i)),
|
| NONE,
|
| kNonStrictMode),
|
| Handle<JSObject>());
|
| @@ -10462,9 +10587,12 @@
|
| ScopeTypeCatch
|
| };
|
|
|
| - ScopeIterator(Isolate* isolate, JavaScriptFrame* frame)
|
| + ScopeIterator(Isolate* isolate,
|
| + JavaScriptFrame* frame,
|
| + int inlined_frame_index)
|
| : isolate_(isolate),
|
| frame_(frame),
|
| + inlined_frame_index_(inlined_frame_index),
|
| function_(JSFunction::cast(frame->function())),
|
| context_(Context::cast(frame->context())),
|
| local_done_(false),
|
| @@ -10549,7 +10677,7 @@
|
| return Handle<JSObject>(CurrentContext()->global());
|
| case ScopeIterator::ScopeTypeLocal:
|
| // Materialize the content of the local scope into a JSObject.
|
| - return MaterializeLocalScope(isolate_, frame_);
|
| + return MaterializeLocalScope(isolate_, frame_, inlined_frame_index_);
|
| case ScopeIterator::ScopeTypeWith:
|
| // Return the with object.
|
| return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
|
| @@ -10629,6 +10757,7 @@
|
| private:
|
| Isolate* isolate_;
|
| JavaScriptFrame* frame_;
|
| + int inlined_frame_index_;
|
| Handle<JSFunction> function_;
|
| Handle<Context> context_;
|
| bool local_done_;
|
| @@ -10657,7 +10786,9 @@
|
|
|
| // Count the visible scopes.
|
| int n = 0;
|
| - for (ScopeIterator it(isolate, frame); !it.Done(); it.Next()) {
|
| + for (ScopeIterator it(isolate, frame, 0);
|
| + !it.Done();
|
| + it.Next()) {
|
| n++;
|
| }
|
|
|
| @@ -10672,14 +10803,15 @@
|
| // Return an array with scope details
|
| // args[0]: number: break id
|
| // args[1]: number: frame index
|
| -// args[2]: number: scope index
|
| +// args[2]: number: inlined frame index
|
| +// args[3]: number: scope index
|
| //
|
| // The array returned contains the following information:
|
| // 0: Scope type
|
| // 1: Scope object
|
| RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
|
| HandleScope scope(isolate);
|
| - ASSERT(args.length() == 3);
|
| + ASSERT(args.length() == 4);
|
|
|
| // Check arguments.
|
| Object* check;
|
| @@ -10688,7 +10820,8 @@
|
| if (!maybe_check->ToObject(&check)) return maybe_check;
|
| }
|
| CONVERT_CHECKED(Smi, wrapped_id, args[1]);
|
| - CONVERT_NUMBER_CHECKED(int, index, Int32, args[2]);
|
| + CONVERT_NUMBER_CHECKED(int, inlined_frame_index, Int32, args[2]);
|
| + CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
|
|
|
| // Get the frame where the debugging is performed.
|
| StackFrame::Id id = UnwrapFrameId(wrapped_id);
|
| @@ -10697,7 +10830,7 @@
|
|
|
| // Find the requested scope.
|
| int n = 0;
|
| - ScopeIterator it(isolate, frame);
|
| + ScopeIterator it(isolate, frame, inlined_frame_index);
|
| for (; !it.Done() && n < index; it.Next()) {
|
| n++;
|
| }
|
| @@ -10727,7 +10860,9 @@
|
| // Print the scopes for the top frame.
|
| StackFrameLocator locator;
|
| JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
|
| - for (ScopeIterator it(isolate, frame); !it.Done(); it.Next()) {
|
| + for (ScopeIterator it(isolate, frame, 0);
|
| + !it.Done();
|
| + it.Next()) {
|
| it.DebugPrint();
|
| }
|
| #endif
|
| @@ -11124,6 +11259,7 @@
|
| // Runtime_DebugEvaluate.
|
| static Handle<Object> GetArgumentsObject(Isolate* isolate,
|
| JavaScriptFrame* frame,
|
| + int inlined_frame_index,
|
| Handle<JSFunction> function,
|
| Handle<SerializedScopeInfo> scope_info,
|
| const ScopeInfo<>* sinfo,
|
| @@ -11147,7 +11283,9 @@
|
| }
|
| }
|
|
|
| - const int length = frame->ComputeParametersCount();
|
| + FrameInspector frame_inspector(frame, inlined_frame_index, isolate);
|
| +
|
| + int length = frame_inspector.GetParametersCount();
|
| Handle<JSObject> arguments =
|
| isolate->factory()->NewArgumentsObject(function, length);
|
| Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
|
| @@ -11155,7 +11293,7 @@
|
| AssertNoAllocation no_gc;
|
| WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
|
| for (int i = 0; i < length; i++) {
|
| - array->set(i, frame->GetParameter(i), mode);
|
| + array->set(i, frame_inspector.GetParameter(i), mode);
|
| }
|
| arguments->set_elements(*array);
|
| return arguments;
|
| @@ -11182,7 +11320,7 @@
|
|
|
| // Check the execution state and decode arguments frame and source to be
|
| // evaluated.
|
| - ASSERT(args.length() == 5);
|
| + ASSERT(args.length() == 6);
|
| Object* check_result;
|
| { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(
|
| RUNTIME_ARGUMENTS(isolate, args));
|
| @@ -11191,9 +11329,10 @@
|
| }
|
| }
|
| CONVERT_CHECKED(Smi, wrapped_id, args[1]);
|
| - CONVERT_ARG_CHECKED(String, source, 2);
|
| - CONVERT_BOOLEAN_CHECKED(disable_break, args[3]);
|
| - Handle<Object> additional_context(args[4]);
|
| + CONVERT_NUMBER_CHECKED(int, inlined_frame_index, Int32, args[2]);
|
| + CONVERT_ARG_CHECKED(String, source, 3);
|
| + CONVERT_BOOLEAN_CHECKED(disable_break, args[4]);
|
| + Handle<Object> additional_context(args[5]);
|
|
|
| // Handle the processing of break.
|
| DisableBreak disable_break_save(disable_break);
|
| @@ -11233,7 +11372,8 @@
|
| #endif
|
|
|
| // Materialize the content of the local scope into a JSObject.
|
| - Handle<JSObject> local_scope = MaterializeLocalScope(isolate, frame);
|
| + Handle<JSObject> local_scope = MaterializeLocalScope(
|
| + isolate, frame, inlined_frame_index);
|
| RETURN_IF_EMPTY_HANDLE(isolate, local_scope);
|
|
|
| // Allocate a new context for the debug evaluation and set the extension
|
| @@ -11282,7 +11422,8 @@
|
| &has_pending_exception);
|
| if (has_pending_exception) return Failure::Exception();
|
|
|
| - Handle<Object> arguments = GetArgumentsObject(isolate, frame,
|
| + Handle<Object> arguments = GetArgumentsObject(isolate,
|
| + frame, inlined_frame_index,
|
| function, scope_info,
|
| &sinfo, function_context);
|
|
|
| @@ -12187,7 +12328,6 @@
|
| #endif // ENABLE_DEBUGGER_SUPPORT
|
|
|
|
|
| -#ifdef ENABLE_LOGGING_AND_PROFILING
|
| RUNTIME_FUNCTION(MaybeObject*, Runtime_ProfilerResume) {
|
| NoHandleAllocation ha;
|
| v8::V8::ResumeProfiler();
|
| @@ -12201,7 +12341,6 @@
|
| return isolate->heap()->undefined_value();
|
| }
|
|
|
| -#endif // ENABLE_LOGGING_AND_PROFILING
|
|
|
| // Finds the script object from the script data. NOTE: This operation uses
|
| // heap traversal to find the function generated for the source position
|
| @@ -12259,8 +12398,9 @@
|
| // call to this function is encountered it is skipped. The seen_caller
|
| // in/out parameter is used to remember if the caller has been seen
|
| // yet.
|
| -static bool ShowFrameInStackTrace(StackFrame* raw_frame, Object* caller,
|
| - bool* seen_caller) {
|
| +static bool ShowFrameInStackTrace(StackFrame* raw_frame,
|
| + Object* caller,
|
| + bool* seen_caller) {
|
| // Only display JS frames.
|
| if (!raw_frame->is_java_script())
|
| return false;
|
| @@ -12273,11 +12413,25 @@
|
| *seen_caller = true;
|
| return false;
|
| }
|
| - // Skip all frames until we've seen the caller. Also, skip the most
|
| - // obvious builtin calls. Some builtin calls (such as Number.ADD
|
| - // which is invoked using 'call') are very difficult to recognize
|
| - // so we're leaving them in for now.
|
| - return *seen_caller && !frame->receiver()->IsJSBuiltinsObject();
|
| + // Skip all frames until we've seen the caller.
|
| + if (!(*seen_caller)) return false;
|
| + // Also, skip the most obvious builtin calls. We recognize builtins
|
| + // as (1) functions called with the builtins object as the receiver and
|
| + // as (2) functions from native scripts called with undefined as the
|
| + // receiver (direct calls to helper functions in the builtins
|
| + // code). Some builtin calls (such as Number.ADD which is invoked
|
| + // using 'call') are very difficult to recognize so we're leaving
|
| + // them in for now.
|
| + if (frame->receiver()->IsJSBuiltinsObject()) {
|
| + return false;
|
| + }
|
| + JSFunction* fun = JSFunction::cast(raw_fun);
|
| + Object* raw_script = fun->shared()->script();
|
| + if (frame->receiver()->IsUndefined() && raw_script->IsScript()) {
|
| + int script_type = Script::cast(raw_script)->type()->value();
|
| + return script_type != Script::TYPE_NATIVE;
|
| + }
|
| + return true;
|
| }
|
|
|
|
|
|
|
| Property changes on: src/runtime.cc
|
| ___________________________________________________________________
|
| Modified: svn:mergeinfo
|
| Merged /branches/bleeding_edge/src/runtime.cc:r8598-8774
|
|
|
|
|