OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stdlib.h> | 5 #include <stdlib.h> |
6 #include <limits> | 6 #include <limits> |
7 | 7 |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #include "src/accessors.h" | 10 #include "src/accessors.h" |
(...skipping 8173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8184 } | 8184 } |
8185 return param_data; | 8185 return param_data; |
8186 } | 8186 } |
8187 } | 8187 } |
8188 | 8188 |
8189 | 8189 |
8190 RUNTIME_FUNCTION(Runtime_FunctionBindArguments) { | 8190 RUNTIME_FUNCTION(Runtime_FunctionBindArguments) { |
8191 HandleScope scope(isolate); | 8191 HandleScope scope(isolate); |
8192 ASSERT(args.length() == 4); | 8192 ASSERT(args.length() == 4); |
8193 CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0); | 8193 CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0); |
8194 RUNTIME_ASSERT(args[3]->IsNumber()); | 8194 CONVERT_ARG_HANDLE_CHECKED(Object, bindee, 1); |
8195 Handle<Object> bindee = args.at<Object>(1); | 8195 CONVERT_ARG_HANDLE_CHECKED(Object, this_object, 2); |
| 8196 CONVERT_NUMBER_ARG_HANDLE_CHECKED(new_length, 3); |
8196 | 8197 |
8197 // TODO(lrn): Create bound function in C++ code from premade shared info. | 8198 // TODO(lrn): Create bound function in C++ code from premade shared info. |
8198 bound_function->shared()->set_bound(true); | 8199 bound_function->shared()->set_bound(true); |
8199 // Get all arguments of calling function (Function.prototype.bind). | 8200 // Get all arguments of calling function (Function.prototype.bind). |
8200 int argc = 0; | 8201 int argc = 0; |
8201 SmartArrayPointer<Handle<Object> > arguments = | 8202 SmartArrayPointer<Handle<Object> > arguments = |
8202 GetCallerArguments(isolate, 0, &argc); | 8203 GetCallerArguments(isolate, 0, &argc); |
8203 // Don't count the this-arg. | 8204 // Don't count the this-arg. |
8204 if (argc > 0) { | 8205 if (argc > 0) { |
8205 RUNTIME_ASSERT(*arguments[0] == args[2]); | 8206 RUNTIME_ASSERT(arguments[0].is_identical_to(this_object)); |
8206 argc--; | 8207 argc--; |
8207 } else { | 8208 } else { |
8208 RUNTIME_ASSERT(args[2]->IsUndefined()); | 8209 RUNTIME_ASSERT(this_object->IsUndefined()); |
8209 } | 8210 } |
8210 // Initialize array of bindings (function, this, and any existing arguments | 8211 // Initialize array of bindings (function, this, and any existing arguments |
8211 // if the function was already bound). | 8212 // if the function was already bound). |
8212 Handle<FixedArray> new_bindings; | 8213 Handle<FixedArray> new_bindings; |
8213 int i; | 8214 int i; |
8214 if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) { | 8215 if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) { |
8215 Handle<FixedArray> old_bindings( | 8216 Handle<FixedArray> old_bindings( |
8216 JSFunction::cast(*bindee)->function_bindings()); | 8217 JSFunction::cast(*bindee)->function_bindings()); |
8217 RUNTIME_ASSERT(old_bindings->length() > JSFunction::kBoundFunctionIndex); | 8218 RUNTIME_ASSERT(old_bindings->length() > JSFunction::kBoundFunctionIndex); |
8218 new_bindings = | 8219 new_bindings = |
8219 isolate->factory()->NewFixedArray(old_bindings->length() + argc); | 8220 isolate->factory()->NewFixedArray(old_bindings->length() + argc); |
8220 bindee = Handle<Object>(old_bindings->get(JSFunction::kBoundFunctionIndex), | 8221 bindee = Handle<Object>(old_bindings->get(JSFunction::kBoundFunctionIndex), |
8221 isolate); | 8222 isolate); |
8222 i = 0; | 8223 i = 0; |
8223 for (int n = old_bindings->length(); i < n; i++) { | 8224 for (int n = old_bindings->length(); i < n; i++) { |
8224 new_bindings->set(i, old_bindings->get(i)); | 8225 new_bindings->set(i, old_bindings->get(i)); |
8225 } | 8226 } |
8226 } else { | 8227 } else { |
8227 int array_size = JSFunction::kBoundArgumentsStartIndex + argc; | 8228 int array_size = JSFunction::kBoundArgumentsStartIndex + argc; |
8228 new_bindings = isolate->factory()->NewFixedArray(array_size); | 8229 new_bindings = isolate->factory()->NewFixedArray(array_size); |
8229 new_bindings->set(JSFunction::kBoundFunctionIndex, *bindee); | 8230 new_bindings->set(JSFunction::kBoundFunctionIndex, *bindee); |
8230 new_bindings->set(JSFunction::kBoundThisIndex, args[2]); | 8231 new_bindings->set(JSFunction::kBoundThisIndex, *this_object); |
8231 i = 2; | 8232 i = 2; |
8232 } | 8233 } |
8233 // Copy arguments, skipping the first which is "this_arg". | 8234 // Copy arguments, skipping the first which is "this_arg". |
8234 for (int j = 0; j < argc; j++, i++) { | 8235 for (int j = 0; j < argc; j++, i++) { |
8235 new_bindings->set(i, *arguments[j + 1]); | 8236 new_bindings->set(i, *arguments[j + 1]); |
8236 } | 8237 } |
8237 new_bindings->set_map_no_write_barrier( | 8238 new_bindings->set_map_no_write_barrier( |
8238 isolate->heap()->fixed_cow_array_map()); | 8239 isolate->heap()->fixed_cow_array_map()); |
8239 bound_function->set_function_bindings(*new_bindings); | 8240 bound_function->set_function_bindings(*new_bindings); |
8240 | 8241 |
8241 // Update length. | 8242 // Update length. Have to remove the prototype first so that map migration |
| 8243 // is happy about the number of fields. |
| 8244 RUNTIME_ASSERT(bound_function->RemovePrototype()); |
| 8245 Handle<Map> bound_function_map( |
| 8246 isolate->native_context()->bound_function_map()); |
| 8247 JSObject::MigrateToMap(bound_function, bound_function_map); |
8242 Handle<String> length_string = isolate->factory()->length_string(); | 8248 Handle<String> length_string = isolate->factory()->length_string(); |
8243 Handle<Object> new_length(args.at<Object>(3)); | |
8244 PropertyAttributes attr = | 8249 PropertyAttributes attr = |
8245 static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM | READ_ONLY); | 8250 static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM | READ_ONLY); |
8246 Runtime::ForceSetObjectProperty( | 8251 JSObject::SetOwnPropertyIgnoreAttributes(bound_function, length_string, |
8247 bound_function, length_string, new_length, attr).Assert(); | 8252 new_length, attr); |
8248 return *bound_function; | 8253 return *bound_function; |
8249 } | 8254 } |
8250 | 8255 |
8251 | 8256 |
8252 RUNTIME_FUNCTION(Runtime_BoundFunctionGetBindings) { | 8257 RUNTIME_FUNCTION(Runtime_BoundFunctionGetBindings) { |
8253 HandleScope handles(isolate); | 8258 HandleScope handles(isolate); |
8254 ASSERT(args.length() == 1); | 8259 ASSERT(args.length() == 1); |
8255 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callable, 0); | 8260 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callable, 0); |
8256 if (callable->IsJSFunction()) { | 8261 if (callable->IsJSFunction()) { |
8257 Handle<JSFunction> function = Handle<JSFunction>::cast(callable); | 8262 Handle<JSFunction> function = Handle<JSFunction>::cast(callable); |
(...skipping 6944 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15202 } | 15207 } |
15203 return NULL; | 15208 return NULL; |
15204 } | 15209 } |
15205 | 15210 |
15206 | 15211 |
15207 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { | 15212 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { |
15208 return &(kIntrinsicFunctions[static_cast<int>(id)]); | 15213 return &(kIntrinsicFunctions[static_cast<int>(id)]); |
15209 } | 15214 } |
15210 | 15215 |
15211 } } // namespace v8::internal | 15216 } } // namespace v8::internal |
OLD | NEW |