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 |