| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 1912 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1923 | 1923 |
| 1924 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionMarkNameShouldPrintAsAnonymous) { | 1924 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionMarkNameShouldPrintAsAnonymous) { |
| 1925 NoHandleAllocation ha; | 1925 NoHandleAllocation ha; |
| 1926 ASSERT(args.length() == 1); | 1926 ASSERT(args.length() == 1); |
| 1927 CONVERT_CHECKED(JSFunction, f, args[0]); | 1927 CONVERT_CHECKED(JSFunction, f, args[0]); |
| 1928 f->shared()->set_name_should_print_as_anonymous(true); | 1928 f->shared()->set_name_should_print_as_anonymous(true); |
| 1929 return isolate->heap()->undefined_value(); | 1929 return isolate->heap()->undefined_value(); |
| 1930 } | 1930 } |
| 1931 | 1931 |
| 1932 | 1932 |
| 1933 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetBound) { | |
| 1934 HandleScope scope(isolate); | |
| 1935 ASSERT(args.length() == 1); | |
| 1936 | |
| 1937 CONVERT_CHECKED(JSFunction, fun, args[0]); | |
| 1938 fun->shared()->set_bound(true); | |
| 1939 return isolate->heap()->undefined_value(); | |
| 1940 } | |
| 1941 | |
| 1942 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionRemovePrototype) { | 1933 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionRemovePrototype) { |
| 1943 NoHandleAllocation ha; | 1934 NoHandleAllocation ha; |
| 1944 ASSERT(args.length() == 1); | 1935 ASSERT(args.length() == 1); |
| 1945 | 1936 |
| 1946 CONVERT_CHECKED(JSFunction, f, args[0]); | 1937 CONVERT_CHECKED(JSFunction, f, args[0]); |
| 1947 Object* obj = f->RemovePrototype(); | 1938 Object* obj = f->RemovePrototype(); |
| 1948 if (obj->IsFailure()) return obj; | 1939 if (obj->IsFailure()) return obj; |
| 1949 | 1940 |
| 1950 return isolate->heap()->undefined_value(); | 1941 return isolate->heap()->undefined_value(); |
| 1951 } | 1942 } |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2010 NoHandleAllocation ha; | 2001 NoHandleAllocation ha; |
| 2011 ASSERT(args.length() == 2); | 2002 ASSERT(args.length() == 2); |
| 2012 | 2003 |
| 2013 CONVERT_CHECKED(JSFunction, fun, args[0]); | 2004 CONVERT_CHECKED(JSFunction, fun, args[0]); |
| 2014 CONVERT_CHECKED(Smi, length, args[1]); | 2005 CONVERT_CHECKED(Smi, length, args[1]); |
| 2015 fun->shared()->set_length(length->value()); | 2006 fun->shared()->set_length(length->value()); |
| 2016 return length; | 2007 return length; |
| 2017 } | 2008 } |
| 2018 | 2009 |
| 2019 | 2010 |
| 2020 // Creates a local, readonly, property called length with the correct | |
| 2021 // length (when read by the user). This effectively overwrites the | |
| 2022 // interceptor used to normally provide the length. | |
| 2023 RUNTIME_FUNCTION(MaybeObject*, Runtime_BoundFunctionSetLength) { | |
| 2024 NoHandleAllocation ha; | |
| 2025 ASSERT(args.length() == 2); | |
| 2026 CONVERT_CHECKED(JSFunction, fun, args[0]); | |
| 2027 CONVERT_CHECKED(Smi, length, args[1]); | |
| 2028 MaybeObject* maybe_name = | |
| 2029 isolate->heap()->AllocateStringFromAscii(CStrVector("length")); | |
| 2030 String* name; | |
| 2031 if (!maybe_name->To(&name)) return maybe_name; | |
| 2032 PropertyAttributes attr = | |
| 2033 static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM | READ_ONLY); | |
| 2034 return fun->AddProperty(name, length, attr, kNonStrictMode); | |
| 2035 } | |
| 2036 | |
| 2037 | |
| 2038 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetPrototype) { | 2011 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetPrototype) { |
| 2039 NoHandleAllocation ha; | 2012 NoHandleAllocation ha; |
| 2040 ASSERT(args.length() == 2); | 2013 ASSERT(args.length() == 2); |
| 2041 | 2014 |
| 2042 CONVERT_CHECKED(JSFunction, fun, args[0]); | 2015 CONVERT_CHECKED(JSFunction, fun, args[0]); |
| 2043 ASSERT(fun->should_have_prototype()); | 2016 ASSERT(fun->should_have_prototype()); |
| 2044 Object* obj; | 2017 Object* obj; |
| 2045 { MaybeObject* maybe_obj = | 2018 { MaybeObject* maybe_obj = |
| 2046 Accessors::FunctionSetPrototype(fun, args[1], NULL); | 2019 Accessors::FunctionSetPrototype(fun, args[1], NULL); |
| 2047 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2020 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| (...skipping 5871 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7919 // directly to properties. | 7892 // directly to properties. |
| 7920 PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED; | 7893 PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED; |
| 7921 Handle<JSFunction> result = | 7894 Handle<JSFunction> result = |
| 7922 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, | 7895 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, |
| 7923 context, | 7896 context, |
| 7924 pretenure_flag); | 7897 pretenure_flag); |
| 7925 return *result; | 7898 return *result; |
| 7926 } | 7899 } |
| 7927 | 7900 |
| 7928 | 7901 |
| 7929 static SmartArrayPointer<Handle<Object> > GetNonBoundArguments( | 7902 // Find the arguments of the JavaScript function invocation that called |
| 7930 int bound_argc, | 7903 // into C++ code. Collect these in a newly allocated array of handles (possibly |
| 7904 // prefixed by a number of empty handles). |
| 7905 static SmartArrayPointer<Handle<Object> > GetCallerArguments( |
| 7906 int prefix_argc, |
| 7931 int* total_argc) { | 7907 int* total_argc) { |
| 7932 // Find frame containing arguments passed to the caller. | 7908 // Find frame containing arguments passed to the caller. |
| 7933 JavaScriptFrameIterator it; | 7909 JavaScriptFrameIterator it; |
| 7934 JavaScriptFrame* frame = it.frame(); | 7910 JavaScriptFrame* frame = it.frame(); |
| 7935 List<JSFunction*> functions(2); | 7911 List<JSFunction*> functions(2); |
| 7936 frame->GetFunctions(&functions); | 7912 frame->GetFunctions(&functions); |
| 7937 if (functions.length() > 1) { | 7913 if (functions.length() > 1) { |
| 7938 int inlined_frame_index = functions.length() - 1; | 7914 int inlined_frame_index = functions.length() - 1; |
| 7939 JSFunction* inlined_function = functions[inlined_frame_index]; | 7915 JSFunction* inlined_function = functions[inlined_frame_index]; |
| 7940 int args_count = inlined_function->shared()->formal_parameter_count(); | 7916 int args_count = inlined_function->shared()->formal_parameter_count(); |
| 7941 ScopedVector<SlotRef> args_slots(args_count); | 7917 ScopedVector<SlotRef> args_slots(args_count); |
| 7942 SlotRef::ComputeSlotMappingForArguments(frame, | 7918 SlotRef::ComputeSlotMappingForArguments(frame, |
| 7943 inlined_frame_index, | 7919 inlined_frame_index, |
| 7944 &args_slots); | 7920 &args_slots); |
| 7945 | 7921 |
| 7946 *total_argc = bound_argc + args_count; | 7922 *total_argc = prefix_argc + args_count; |
| 7947 SmartArrayPointer<Handle<Object> > param_data( | 7923 SmartArrayPointer<Handle<Object> > param_data( |
| 7948 NewArray<Handle<Object> >(*total_argc)); | 7924 NewArray<Handle<Object> >(*total_argc)); |
| 7949 for (int i = 0; i < args_count; i++) { | 7925 for (int i = 0; i < args_count; i++) { |
| 7950 Handle<Object> val = args_slots[i].GetValue(); | 7926 Handle<Object> val = args_slots[i].GetValue(); |
| 7951 param_data[bound_argc + i] = val; | 7927 param_data[prefix_argc + i] = val; |
| 7952 } | 7928 } |
| 7953 return param_data; | 7929 return param_data; |
| 7954 } else { | 7930 } else { |
| 7955 it.AdvanceToArgumentsFrame(); | 7931 it.AdvanceToArgumentsFrame(); |
| 7956 frame = it.frame(); | 7932 frame = it.frame(); |
| 7957 int args_count = frame->ComputeParametersCount(); | 7933 int args_count = frame->ComputeParametersCount(); |
| 7958 | 7934 |
| 7959 *total_argc = bound_argc + args_count; | 7935 *total_argc = prefix_argc + args_count; |
| 7960 SmartArrayPointer<Handle<Object> > param_data( | 7936 SmartArrayPointer<Handle<Object> > param_data( |
| 7961 NewArray<Handle<Object> >(*total_argc)); | 7937 NewArray<Handle<Object> >(*total_argc)); |
| 7962 for (int i = 0; i < args_count; i++) { | 7938 for (int i = 0; i < args_count; i++) { |
| 7963 Handle<Object> val = Handle<Object>(frame->GetParameter(i)); | 7939 Handle<Object> val = Handle<Object>(frame->GetParameter(i)); |
| 7964 param_data[bound_argc + i] = val; | 7940 param_data[prefix_argc + i] = val; |
| 7965 } | 7941 } |
| 7966 return param_data; | 7942 return param_data; |
| 7967 } | 7943 } |
| 7968 } | 7944 } |
| 7969 | 7945 |
| 7970 | 7946 |
| 7947 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionBindArguments) { |
| 7948 HandleScope scope(isolate); |
| 7949 ASSERT(args.length() == 4); |
| 7950 CONVERT_ARG_CHECKED(JSFunction, bound_function, 0); |
| 7951 RUNTIME_ASSERT(args[3]->IsNumber()); |
| 7952 Handle<Object> bindee = args.at<Object>(1); |
| 7953 |
| 7954 // TODO(lrn): Create bound function in C++ code from premade shared info. |
| 7955 bound_function->shared()->set_bound(true); |
| 7956 // Get all arguments of calling function (Function.prototype.bind). |
| 7957 int argc = 0; |
| 7958 SmartArrayPointer<Handle<Object> > arguments = GetCallerArguments(0, &argc); |
| 7959 // Don't count the this-arg. |
| 7960 if (argc > 0) { |
| 7961 ASSERT(*arguments[0] == args[2]); |
| 7962 argc--; |
| 7963 } else { |
| 7964 ASSERT(args[2]->IsUndefined()); |
| 7965 } |
| 7966 // Initialize array of bindings (function, this, and any existing arguments |
| 7967 // if the function was already bound). |
| 7968 Handle<FixedArray> new_bindings; |
| 7969 int i; |
| 7970 if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) { |
| 7971 Handle<FixedArray> old_bindings( |
| 7972 JSFunction::cast(*bindee)->function_bindings()); |
| 7973 new_bindings = |
| 7974 isolate->factory()->NewFixedArray(old_bindings->length() + argc); |
| 7975 bindee = Handle<Object>(old_bindings->get(JSFunction::kBoundFunctionIndex)); |
| 7976 i = 0; |
| 7977 for (int n = old_bindings->length(); i < n; i++) { |
| 7978 new_bindings->set(i, old_bindings->get(i)); |
| 7979 } |
| 7980 } else { |
| 7981 int array_size = JSFunction::kBoundArgumentsStartIndex + argc; |
| 7982 new_bindings = isolate->factory()->NewFixedArray(array_size); |
| 7983 new_bindings->set(JSFunction::kBoundFunctionIndex, *bindee); |
| 7984 new_bindings->set(JSFunction::kBoundThisIndex, args[2]); |
| 7985 i = 2; |
| 7986 } |
| 7987 // Copy arguments, skipping the first which is "this_arg". |
| 7988 for (int j = 0; j < argc; j++, i++) { |
| 7989 new_bindings->set(i, *arguments[j + 1]); |
| 7990 } |
| 7991 new_bindings->set_map(isolate->heap()->fixed_cow_array_map()); |
| 7992 bound_function->set_function_bindings(*new_bindings); |
| 7993 |
| 7994 // Update length. |
| 7995 Handle<String> length_symbol = isolate->factory()->length_symbol(); |
| 7996 Handle<Object> new_length(args.at<Object>(3)); |
| 7997 PropertyAttributes attr = |
| 7998 static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM | READ_ONLY); |
| 7999 ForceSetProperty(bound_function, length_symbol, new_length, attr); |
| 8000 return *bound_function; |
| 8001 } |
| 8002 |
| 8003 |
| 8004 RUNTIME_FUNCTION(MaybeObject*, Runtime_BoundFunctionGetBindings) { |
| 8005 HandleScope handles(isolate); |
| 8006 ASSERT(args.length() == 1); |
| 8007 CONVERT_ARG_CHECKED(JSObject, callable, 0); |
| 8008 if (callable->IsJSFunction()) { |
| 8009 Handle<JSFunction> function = Handle<JSFunction>::cast(callable); |
| 8010 if (function->shared()->bound()) { |
| 8011 Handle<FixedArray> bindings(function->function_bindings()); |
| 8012 ASSERT(bindings->map() == isolate->heap()->fixed_cow_array_map()); |
| 8013 return *isolate->factory()->NewJSArrayWithElements(bindings); |
| 8014 } |
| 8015 } |
| 8016 return isolate->heap()->undefined_value(); |
| 8017 } |
| 8018 |
| 8019 |
| 7971 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObjectFromBound) { | 8020 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObjectFromBound) { |
| 7972 HandleScope scope(isolate); | 8021 HandleScope scope(isolate); |
| 7973 ASSERT(args.length() == 2); | 8022 ASSERT(args.length() == 1); |
| 7974 // First argument is a function to use as a constructor. | 8023 // First argument is a function to use as a constructor. |
| 7975 CONVERT_ARG_CHECKED(JSFunction, function, 0); | 8024 CONVERT_ARG_CHECKED(JSFunction, function, 0); |
| 8025 RUNTIME_ASSERT(function->shared()->bound()); |
| 7976 | 8026 |
| 7977 // Second argument is either null or an array of bound arguments. | 8027 // The argument is a bound function. Extract its bound arguments |
| 7978 Handle<FixedArray> bound_args; | 8028 // and callable. |
| 7979 int bound_argc = 0; | 8029 Handle<FixedArray> bound_args = |
| 7980 if (!args[1]->IsNull()) { | 8030 Handle<FixedArray>(FixedArray::cast(function->function_bindings())); |
| 7981 CONVERT_ARG_CHECKED(JSArray, params, 1); | 8031 int bound_argc = bound_args->length() - JSFunction::kBoundArgumentsStartIndex; |
| 7982 RUNTIME_ASSERT(params->HasFastTypeElements()); | 8032 Handle<Object> bound_function( |
| 7983 bound_args = Handle<FixedArray>(FixedArray::cast(params->elements())); | 8033 JSReceiver::cast(bound_args->get(JSFunction::kBoundFunctionIndex))); |
| 7984 bound_argc = Smi::cast(params->length())->value(); | 8034 ASSERT(!bound_function->IsJSFunction() || |
| 7985 } | 8035 !Handle<JSFunction>::cast(bound_function)->shared()->bound()); |
| 7986 | 8036 |
| 7987 int total_argc = 0; | 8037 int total_argc = 0; |
| 7988 SmartArrayPointer<Handle<Object> > param_data = | 8038 SmartArrayPointer<Handle<Object> > param_data = |
| 7989 GetNonBoundArguments(bound_argc, &total_argc); | 8039 GetCallerArguments(bound_argc, &total_argc); |
| 7990 for (int i = 0; i < bound_argc; i++) { | 8040 for (int i = 0; i < bound_argc; i++) { |
| 7991 Handle<Object> val = Handle<Object>(bound_args->get(i)); | 8041 param_data[i] = Handle<Object>(bound_args->get( |
| 7992 param_data[i] = val; | 8042 JSFunction::kBoundArgumentsStartIndex + i)); |
| 7993 } | 8043 } |
| 7994 | 8044 |
| 8045 if (!bound_function->IsJSFunction()) { |
| 8046 bool exception_thrown; |
| 8047 bound_function = Execution::TryGetConstructorDelegate(bound_function, |
| 8048 &exception_thrown); |
| 8049 if (exception_thrown) return Failure::Exception(); |
| 8050 } |
| 8051 ASSERT(bound_function->IsJSFunction()); |
| 8052 |
| 7995 bool exception = false; | 8053 bool exception = false; |
| 7996 Handle<Object> result = | 8054 Handle<Object> result = |
| 7997 Execution::New(function, total_argc, *param_data, &exception); | 8055 Execution::New(Handle<JSFunction>::cast(bound_function), |
| 8056 total_argc, *param_data, &exception); |
| 7998 if (exception) { | 8057 if (exception) { |
| 7999 return Failure::Exception(); | 8058 return Failure::Exception(); |
| 8000 } | 8059 } |
| 8001 | |
| 8002 ASSERT(!result.is_null()); | 8060 ASSERT(!result.is_null()); |
| 8003 return *result; | 8061 return *result; |
| 8004 } | 8062 } |
| 8005 | 8063 |
| 8006 | 8064 |
| 8007 static void TrySettingInlineConstructStub(Isolate* isolate, | 8065 static void TrySettingInlineConstructStub(Isolate* isolate, |
| 8008 Handle<JSFunction> function) { | 8066 Handle<JSFunction> function) { |
| 8009 Handle<Object> prototype = isolate->factory()->null_value(); | 8067 Handle<Object> prototype = isolate->factory()->null_value(); |
| 8010 if (function->has_instance_prototype()) { | 8068 if (function->has_instance_prototype()) { |
| 8011 prototype = Handle<Object>(function->instance_prototype(), isolate); | 8069 prototype = Handle<Object>(function->instance_prototype(), isolate); |
| (...skipping 5276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13288 } else { | 13346 } else { |
| 13289 // Handle last resort GC and make sure to allow future allocations | 13347 // Handle last resort GC and make sure to allow future allocations |
| 13290 // to grow the heap without causing GCs (if possible). | 13348 // to grow the heap without causing GCs (if possible). |
| 13291 isolate->counters()->gc_last_resort_from_js()->Increment(); | 13349 isolate->counters()->gc_last_resort_from_js()->Increment(); |
| 13292 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags); | 13350 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags); |
| 13293 } | 13351 } |
| 13294 } | 13352 } |
| 13295 | 13353 |
| 13296 | 13354 |
| 13297 } } // namespace v8::internal | 13355 } } // namespace v8::internal |
| OLD | NEW |