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 1907 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1918 | 1918 |
1919 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionMarkNameShouldPrintAsAnonymous) { | 1919 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionMarkNameShouldPrintAsAnonymous) { |
1920 NoHandleAllocation ha; | 1920 NoHandleAllocation ha; |
1921 ASSERT(args.length() == 1); | 1921 ASSERT(args.length() == 1); |
1922 CONVERT_CHECKED(JSFunction, f, args[0]); | 1922 CONVERT_CHECKED(JSFunction, f, args[0]); |
1923 f->shared()->set_name_should_print_as_anonymous(true); | 1923 f->shared()->set_name_should_print_as_anonymous(true); |
1924 return isolate->heap()->undefined_value(); | 1924 return isolate->heap()->undefined_value(); |
1925 } | 1925 } |
1926 | 1926 |
1927 | 1927 |
1928 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetBound) { | |
1929 HandleScope scope(isolate); | |
1930 ASSERT(args.length() == 1); | |
1931 | |
1932 CONVERT_CHECKED(JSFunction, fun, args[0]); | |
1933 fun->shared()->set_bound(true); | |
1934 return isolate->heap()->undefined_value(); | |
1935 } | |
1936 | |
1937 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionRemovePrototype) { | 1928 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionRemovePrototype) { |
1938 NoHandleAllocation ha; | 1929 NoHandleAllocation ha; |
1939 ASSERT(args.length() == 1); | 1930 ASSERT(args.length() == 1); |
1940 | 1931 |
1941 CONVERT_CHECKED(JSFunction, f, args[0]); | 1932 CONVERT_CHECKED(JSFunction, f, args[0]); |
1942 Object* obj = f->RemovePrototype(); | 1933 Object* obj = f->RemovePrototype(); |
1943 if (obj->IsFailure()) return obj; | 1934 if (obj->IsFailure()) return obj; |
1944 | 1935 |
1945 return isolate->heap()->undefined_value(); | 1936 return isolate->heap()->undefined_value(); |
1946 } | 1937 } |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2005 NoHandleAllocation ha; | 1996 NoHandleAllocation ha; |
2006 ASSERT(args.length() == 2); | 1997 ASSERT(args.length() == 2); |
2007 | 1998 |
2008 CONVERT_CHECKED(JSFunction, fun, args[0]); | 1999 CONVERT_CHECKED(JSFunction, fun, args[0]); |
2009 CONVERT_CHECKED(Smi, length, args[1]); | 2000 CONVERT_CHECKED(Smi, length, args[1]); |
2010 fun->shared()->set_length(length->value()); | 2001 fun->shared()->set_length(length->value()); |
2011 return length; | 2002 return length; |
2012 } | 2003 } |
2013 | 2004 |
2014 | 2005 |
2015 // Creates a local, readonly, property called length with the correct | |
2016 // length (when read by the user). This effectively overwrites the | |
2017 // interceptor used to normally provide the length. | |
2018 RUNTIME_FUNCTION(MaybeObject*, Runtime_BoundFunctionSetLength) { | |
2019 NoHandleAllocation ha; | |
2020 ASSERT(args.length() == 2); | |
2021 CONVERT_CHECKED(JSFunction, fun, args[0]); | |
2022 CONVERT_CHECKED(Smi, length, args[1]); | |
2023 MaybeObject* maybe_name = | |
2024 isolate->heap()->AllocateStringFromAscii(CStrVector("length")); | |
2025 String* name; | |
2026 if (!maybe_name->To(&name)) return maybe_name; | |
2027 PropertyAttributes attr = | |
2028 static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM | READ_ONLY); | |
2029 return fun->AddProperty(name, length, attr, kNonStrictMode); | |
2030 } | |
2031 | |
2032 | |
2033 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetPrototype) { | 2006 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetPrototype) { |
2034 NoHandleAllocation ha; | 2007 NoHandleAllocation ha; |
2035 ASSERT(args.length() == 2); | 2008 ASSERT(args.length() == 2); |
2036 | 2009 |
2037 CONVERT_CHECKED(JSFunction, fun, args[0]); | 2010 CONVERT_CHECKED(JSFunction, fun, args[0]); |
2038 ASSERT(fun->should_have_prototype()); | 2011 ASSERT(fun->should_have_prototype()); |
2039 Object* obj; | 2012 Object* obj; |
2040 { MaybeObject* maybe_obj = | 2013 { MaybeObject* maybe_obj = |
2041 Accessors::FunctionSetPrototype(fun, args[1], NULL); | 2014 Accessors::FunctionSetPrototype(fun, args[1], NULL); |
2042 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2015 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
(...skipping 5871 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7914 // directly to properties. | 7887 // directly to properties. |
7915 PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED; | 7888 PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED; |
7916 Handle<JSFunction> result = | 7889 Handle<JSFunction> result = |
7917 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, | 7890 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, |
7918 context, | 7891 context, |
7919 pretenure_flag); | 7892 pretenure_flag); |
7920 return *result; | 7893 return *result; |
7921 } | 7894 } |
7922 | 7895 |
7923 | 7896 |
7924 static SmartArrayPointer<Handle<Object> > GetNonBoundArguments( | 7897 // Find the arguments of the JavaScript function invocation that called |
7925 int bound_argc, | 7898 // into C++ code. Collect these in a newly allocated array of handles (possibly |
7899 // prefixed by a number of empty handles). | |
7900 static SmartArrayPointer<Handle<Object> > GetCallerArguments( | |
7901 int prefix_argc, | |
7926 int* total_argc) { | 7902 int* total_argc) { |
7927 // Find frame containing arguments passed to the caller. | 7903 // Find frame containing arguments passed to the caller. |
7928 JavaScriptFrameIterator it; | 7904 JavaScriptFrameIterator it; |
7929 JavaScriptFrame* frame = it.frame(); | 7905 JavaScriptFrame* frame = it.frame(); |
7930 List<JSFunction*> functions(2); | 7906 List<JSFunction*> functions(2); |
7931 frame->GetFunctions(&functions); | 7907 frame->GetFunctions(&functions); |
7932 if (functions.length() > 1) { | 7908 if (functions.length() > 1) { |
7933 int inlined_frame_index = functions.length() - 1; | 7909 int inlined_frame_index = functions.length() - 1; |
7934 JSFunction* inlined_function = functions[inlined_frame_index]; | 7910 JSFunction* inlined_function = functions[inlined_frame_index]; |
7935 int args_count = inlined_function->shared()->formal_parameter_count(); | 7911 int args_count = inlined_function->shared()->formal_parameter_count(); |
7936 ScopedVector<SlotRef> args_slots(args_count); | 7912 ScopedVector<SlotRef> args_slots(args_count); |
7937 SlotRef::ComputeSlotMappingForArguments(frame, | 7913 SlotRef::ComputeSlotMappingForArguments(frame, |
7938 inlined_frame_index, | 7914 inlined_frame_index, |
7939 &args_slots); | 7915 &args_slots); |
7940 | 7916 |
7941 *total_argc = bound_argc + args_count; | 7917 *total_argc = prefix_argc + args_count; |
7942 SmartArrayPointer<Handle<Object> > param_data( | 7918 SmartArrayPointer<Handle<Object> > param_data( |
7943 NewArray<Handle<Object> >(*total_argc)); | 7919 NewArray<Handle<Object> >(*total_argc)); |
7944 for (int i = 0; i < args_count; i++) { | 7920 for (int i = 0; i < args_count; i++) { |
7945 Handle<Object> val = args_slots[i].GetValue(); | 7921 Handle<Object> val = args_slots[i].GetValue(); |
7946 param_data[bound_argc + i] = val; | 7922 param_data[prefix_argc + i] = val; |
7947 } | 7923 } |
7948 return param_data; | 7924 return param_data; |
7949 } else { | 7925 } else { |
7950 it.AdvanceToArgumentsFrame(); | 7926 it.AdvanceToArgumentsFrame(); |
7951 frame = it.frame(); | 7927 frame = it.frame(); |
7952 int args_count = frame->ComputeParametersCount(); | 7928 int args_count = frame->ComputeParametersCount(); |
7953 | 7929 |
7954 *total_argc = bound_argc + args_count; | 7930 *total_argc = prefix_argc + args_count; |
7955 SmartArrayPointer<Handle<Object> > param_data( | 7931 SmartArrayPointer<Handle<Object> > param_data( |
7956 NewArray<Handle<Object> >(*total_argc)); | 7932 NewArray<Handle<Object> >(*total_argc)); |
7957 for (int i = 0; i < args_count; i++) { | 7933 for (int i = 0; i < args_count; i++) { |
7958 Handle<Object> val = Handle<Object>(frame->GetParameter(i)); | 7934 Handle<Object> val = Handle<Object>(frame->GetParameter(i)); |
7959 param_data[bound_argc + i] = val; | 7935 param_data[prefix_argc + i] = val; |
7960 } | 7936 } |
7961 return param_data; | 7937 return param_data; |
7962 } | 7938 } |
7963 } | 7939 } |
7964 | 7940 |
7965 | 7941 |
7942 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionBindArguments) { | |
7943 HandleScope scope(isolate); | |
7944 ASSERT(args.length() == 3); | |
7945 CONVERT_ARG_CHECKED(JSFunction, bound_function, 0); | |
7946 Handle<Object> bindee = args.at<Object>(1); | |
7947 | |
7948 // TODO(lrn): Create bound function in C++ code from premade shared info. | |
7949 bound_function->shared()->set_bound(true); | |
7950 // Get all arguments of calling function (Function.prototype.bind). | |
7951 int argc = 0; | |
7952 SmartArrayPointer<Handle<Object> > arguments = GetCallerArguments(0, &argc); | |
7953 // Don't count the this-arg. | |
7954 if (argc > 0) { | |
7955 ASSERT(*arguments[0] == args[2]); | |
7956 argc--; | |
7957 } else { | |
7958 ASSERT(args[2]->IsUndefined()); | |
7959 } | |
7960 // Initialize array of bindings (function, this, and any existing arguments | |
7961 // if the function was already bound). | |
7962 int total_argc; | |
7963 Handle<FixedArray> new_bindings; | |
7964 int i; | |
7965 if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) { | |
7966 Handle<FixedArray> old_bindings( | |
7967 JSFunction::cast(*bindee)->function_bindings()); | |
7968 new_bindings = | |
7969 isolate->factory()->NewFixedArray(old_bindings->length() + argc); | |
7970 bindee = Handle<Object>(old_bindings->get(JSFunction::kBoundFunctionIndex)); | |
7971 i = 0; | |
7972 for (int n = old_bindings->length(); i < n; i++) { | |
7973 new_bindings->set(i, old_bindings->get(i)); | |
7974 } | |
7975 total_argc = argc + | |
7976 old_bindings->length() - JSFunction::kBoundArgumentsStartIndex; | |
7977 } else { | |
7978 int array_size = JSFunction::kBoundArgumentsStartIndex + argc; | |
7979 new_bindings = isolate->factory()->NewFixedArray(array_size); | |
7980 new_bindings->set(JSFunction::kBoundFunctionIndex, *bindee); | |
7981 new_bindings->set(JSFunction::kBoundThisIndex, args[2]); | |
7982 i = 2; | |
7983 total_argc = argc; | |
7984 } | |
7985 // Copy arguments, skipping the first which is "this_arg". | |
7986 for (int j = 0; j < argc; j++, i++) { | |
7987 new_bindings->set(i, *arguments[j + 1]); | |
7988 } | |
7989 new_bindings->set_map(isolate->heap()->fixed_cow_array_map()); | |
7990 bound_function->set_function_bindings(*new_bindings); | |
7991 // Update length. | |
7992 if (!bindee->IsJSFunction()) { | |
7993 bindee = Execution::GetFunctionDelegate(bindee); | |
rossberg
2011/10/13 14:25:01
Unfortunately, that is not quite right for proxies
Lasse Reichstein
2011/10/14 11:19:37
I think it's an easy fix, if we just read the leng
rossberg
2011/10/17 11:49:08
Yes, that's one of the spec issues I raised. The c
| |
7994 } | |
7995 int length = JSFunction::cast(*bindee)->shared()->length(); | |
7996 int new_length = length - total_argc; | |
7997 if (new_length < 0) new_length = 0; | |
7998 Handle<String> length_symbol = isolate->factory()->length_symbol(); | |
7999 PropertyAttributes attr = | |
8000 static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM | READ_ONLY); | |
8001 ForceSetProperty(bound_function, length_symbol, | |
8002 Handle<Smi>(Smi::FromInt(new_length)), attr); | |
8003 return *bound_function; | |
8004 } | |
8005 | |
8006 | |
8007 RUNTIME_FUNCTION(MaybeObject*, Runtime_BoundFunctionGetBindings) { | |
8008 HandleScope handles(isolate); | |
8009 ASSERT(args.length() == 1); | |
8010 CONVERT_ARG_CHECKED(JSObject, callable, 0); | |
8011 if (callable->IsJSFunction()) { | |
8012 Handle<JSFunction> function = Handle<JSFunction>::cast(callable); | |
8013 if (function->shared()->bound()) { | |
8014 Handle<FixedArray> bindings(function->function_bindings()); | |
8015 ASSERT(bindings->map() == isolate->heap()->fixed_cow_array_map()); | |
8016 return *isolate->factory()->NewJSArrayWithElements(bindings); | |
8017 } | |
8018 } | |
8019 return isolate->heap()->undefined_value(); | |
8020 } | |
8021 | |
8022 | |
7966 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObjectFromBound) { | 8023 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObjectFromBound) { |
7967 HandleScope scope(isolate); | 8024 HandleScope scope(isolate); |
7968 ASSERT(args.length() == 2); | 8025 ASSERT(args.length() == 1); |
7969 // First argument is a function to use as a constructor. | 8026 // First argument is a function to use as a constructor. |
7970 CONVERT_ARG_CHECKED(JSFunction, function, 0); | 8027 CONVERT_ARG_CHECKED(JSFunction, function, 0); |
8028 RUNTIME_ASSERT(function->shared()->bound()); | |
7971 | 8029 |
7972 // Second argument is either null or an array of bound arguments. | 8030 // The argument is a bound function. Extract its bound arguments |
7973 Handle<FixedArray> bound_args; | 8031 // and callable. |
7974 int bound_argc = 0; | 8032 Handle<FixedArray> bound_args = |
7975 if (!args[1]->IsNull()) { | 8033 Handle<FixedArray>(FixedArray::cast(function->function_bindings())); |
7976 CONVERT_ARG_CHECKED(JSArray, params, 1); | 8034 int bound_argc = bound_args->length() - JSFunction::kBoundArgumentsStartIndex; |
7977 RUNTIME_ASSERT(params->HasFastTypeElements()); | 8035 Handle<Object> bound_function( |
7978 bound_args = Handle<FixedArray>(FixedArray::cast(params->elements())); | 8036 JSReceiver::cast(bound_args->get(JSFunction::kBoundFunctionIndex))); |
7979 bound_argc = Smi::cast(params->length())->value(); | 8037 ASSERT(!bound_function->IsJSFunction() || |
7980 } | 8038 !Handle<JSFunction>::cast(bound_function)->shared()->bound()); |
7981 | 8039 |
7982 int total_argc = 0; | 8040 int total_argc = 0; |
7983 SmartArrayPointer<Handle<Object> > param_data = | 8041 SmartArrayPointer<Handle<Object> > param_data = |
7984 GetNonBoundArguments(bound_argc, &total_argc); | 8042 GetCallerArguments(bound_argc, &total_argc); |
7985 for (int i = 0; i < bound_argc; i++) { | 8043 for (int i = 0; i < bound_argc; i++) { |
7986 Handle<Object> val = Handle<Object>(bound_args->get(i)); | 8044 param_data[i] = Handle<Object>(bound_args->get( |
7987 param_data[i] = val; | 8045 JSFunction::kBoundArgumentsStartIndex + i)); |
7988 } | 8046 } |
7989 | 8047 |
8048 if (!bound_function->IsJSFunction()) { | |
8049 bool exception_thrown; | |
8050 bound_function = Execution::TryGetConstructorDelegate(bound_function, | |
8051 &exception_thrown); | |
8052 if (exception_thrown) return Failure::Exception(); | |
8053 } | |
8054 ASSERT(bound_function->IsJSFunction()); | |
8055 | |
7990 bool exception = false; | 8056 bool exception = false; |
7991 Handle<Object> result = | 8057 Handle<Object> result = |
7992 Execution::New(function, total_argc, *param_data, &exception); | 8058 Execution::New(Handle<JSFunction>::cast(bound_function), |
8059 total_argc, *param_data, &exception); | |
7993 if (exception) { | 8060 if (exception) { |
7994 return Failure::Exception(); | 8061 return Failure::Exception(); |
7995 } | 8062 } |
7996 | |
7997 ASSERT(!result.is_null()); | 8063 ASSERT(!result.is_null()); |
7998 return *result; | 8064 return *result; |
7999 } | 8065 } |
8000 | 8066 |
8001 | 8067 |
8002 static void TrySettingInlineConstructStub(Isolate* isolate, | 8068 static void TrySettingInlineConstructStub(Isolate* isolate, |
8003 Handle<JSFunction> function) { | 8069 Handle<JSFunction> function) { |
8004 Handle<Object> prototype = isolate->factory()->null_value(); | 8070 Handle<Object> prototype = isolate->factory()->null_value(); |
8005 if (function->has_instance_prototype()) { | 8071 if (function->has_instance_prototype()) { |
8006 prototype = Handle<Object>(function->instance_prototype(), isolate); | 8072 prototype = Handle<Object>(function->instance_prototype(), isolate); |
(...skipping 5236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
13243 } else { | 13309 } else { |
13244 // Handle last resort GC and make sure to allow future allocations | 13310 // Handle last resort GC and make sure to allow future allocations |
13245 // to grow the heap without causing GCs (if possible). | 13311 // to grow the heap without causing GCs (if possible). |
13246 isolate->counters()->gc_last_resort_from_js()->Increment(); | 13312 isolate->counters()->gc_last_resort_from_js()->Increment(); |
13247 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags); | 13313 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags); |
13248 } | 13314 } |
13249 } | 13315 } |
13250 | 13316 |
13251 | 13317 |
13252 } } // namespace v8::internal | 13318 } } // namespace v8::internal |
OLD | NEW |