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