Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/builtins/builtins-function.cc

Issue 2532483002: [stubs] Port FastFunctionBindStub to TF (Closed)
Patch Set: Review feedback Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/builtins/builtins-array.cc ('k') | src/code-factory.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 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 "src/builtins/builtins.h" 5 #include "src/builtins/builtins.h"
6 #include "src/builtins/builtins-utils.h" 6 #include "src/builtins/builtins-utils.h"
7 7
8 #include "src/code-factory.h"
8 #include "src/compiler.h" 9 #include "src/compiler.h"
9 #include "src/string-builder.h" 10 #include "src/string-builder.h"
10 11
11 namespace v8 { 12 namespace v8 {
12 namespace internal { 13 namespace internal {
13 14
14 namespace { 15 namespace {
15 16
16 // ES6 section 19.2.1.1.1 CreateDynamicFunction 17 // ES6 section 19.2.1.1.1 CreateDynamicFunction
17 MaybeHandle<Object> CreateDynamicFunction(Isolate* isolate, 18 MaybeHandle<Object> CreateDynamicFunction(Isolate* isolate,
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 &it, name, it.property_attributes())); 249 &it, name, it.property_attributes()));
249 } 250 }
250 return *function; 251 return *function;
251 } 252 }
252 253
253 } // namespace 254 } // namespace
254 255
255 // ES6 section 19.2.3.2 Function.prototype.bind ( thisArg, ...args ) 256 // ES6 section 19.2.3.2 Function.prototype.bind ( thisArg, ...args )
256 BUILTIN(FunctionPrototypeBind) { return DoFunctionBind(isolate, args); } 257 BUILTIN(FunctionPrototypeBind) { return DoFunctionBind(isolate, args); }
257 258
259 void Builtins::Generate_FastFunctionPrototypeBind(
260 compiler::CodeAssemblerState* state) {
261 using compiler::Node;
262 typedef CodeStubAssembler::Label Label;
263 typedef CodeStubAssembler::Variable Variable;
264
265 CodeStubAssembler assembler(state);
266 Label slow(&assembler);
267
268 Node* argc = assembler.Parameter(BuiltinDescriptor::kArgumentsCount);
269 Node* context = assembler.Parameter(BuiltinDescriptor::kContext);
270 Node* new_target = assembler.Parameter(BuiltinDescriptor::kNewTarget);
271
272 CodeStubArguments args(&assembler, argc);
273
274 // Check that receiver has instance type of JS_FUNCTION_TYPE
275 Node* receiver = args.GetReceiver();
276 assembler.GotoIf(assembler.TaggedIsSmi(receiver), &slow);
277
278 Node* receiver_map = assembler.LoadMap(receiver);
279 Node* instance_type = assembler.LoadMapInstanceType(receiver_map);
280 assembler.GotoIf(
281 assembler.Word32NotEqual(instance_type,
282 assembler.Int32Constant(JS_FUNCTION_TYPE)),
283 &slow);
284
285 // Disallow binding of slow-mode functions. We need to figure out whether the
286 // length and name property are in the original state.
287 assembler.Comment("Disallow binding of slow-mode functions");
288 assembler.GotoIf(assembler.IsDictionaryMap(receiver_map), &slow);
289
290 // Check whether the length and name properties are still present as
291 // AccessorInfo objects. In that case, their value can be recomputed even if
292 // the actual value on the object changes.
293 assembler.Comment("Check descriptor array length");
294 Node* descriptors = assembler.LoadMapDescriptors(receiver_map);
295 Node* descriptors_length = assembler.LoadFixedArrayBaseLength(descriptors);
296 assembler.GotoIf(assembler.SmiLessThanOrEqual(descriptors_length,
297 assembler.SmiConstant(1)),
298 &slow);
299
300 // Check whether the length and name properties are still present as
301 // AccessorInfo objects. In that case, their value can be recomputed even if
302 // the actual value on the object changes.
303 assembler.Comment("Check name and length properties");
304 const int length_index = JSFunction::kLengthDescriptorIndex;
305 Node* maybe_length = assembler.LoadFixedArrayElement(
306 descriptors, DescriptorArray::ToKeyIndex(length_index));
307 assembler.GotoIf(
308 assembler.WordNotEqual(maybe_length,
309 assembler.LoadRoot(Heap::klength_stringRootIndex)),
310 &slow);
311
312 Node* maybe_length_accessor = assembler.LoadFixedArrayElement(
313 descriptors, DescriptorArray::ToValueIndex(length_index));
314 assembler.GotoIf(assembler.TaggedIsSmi(maybe_length_accessor), &slow);
315 Node* length_value_map = assembler.LoadMap(maybe_length_accessor);
316 assembler.GotoUnless(assembler.IsAccessorInfoMap(length_value_map), &slow);
317
318 const int name_index = JSFunction::kNameDescriptorIndex;
319 Node* maybe_name = assembler.LoadFixedArrayElement(
320 descriptors, DescriptorArray::ToKeyIndex(name_index));
321 assembler.GotoIf(
322 assembler.WordNotEqual(maybe_name,
323 assembler.LoadRoot(Heap::kname_stringRootIndex)),
324 &slow);
325
326 Node* maybe_name_accessor = assembler.LoadFixedArrayElement(
327 descriptors, DescriptorArray::ToValueIndex(name_index));
328 assembler.GotoIf(assembler.TaggedIsSmi(maybe_name_accessor), &slow);
329 Node* name_value_map = assembler.LoadMap(maybe_name_accessor);
330 assembler.GotoUnless(assembler.IsAccessorInfoMap(name_value_map), &slow);
331
332 // Choose the right bound function map based on whether the target is
333 // constructable.
334 assembler.Comment("Choose the right bound function map");
335 Variable bound_function_map(&assembler, MachineRepresentation::kTagged);
336 Label with_constructor(&assembler);
337 CodeStubAssembler::VariableList vars({&bound_function_map}, assembler.zone());
338 Node* native_context = assembler.LoadNativeContext(context);
339
340 Label map_done(&assembler, vars);
341 Node* bit_field = assembler.LoadMapBitField(receiver_map);
342 int mask = static_cast<int>(1 << Map::kIsConstructor);
343 assembler.GotoIf(assembler.IsSetWord32(bit_field, mask), &with_constructor);
344
345 bound_function_map.Bind(assembler.LoadContextElement(
346 native_context, Context::BOUND_FUNCTION_WITHOUT_CONSTRUCTOR_MAP_INDEX));
347 assembler.Goto(&map_done);
348
349 assembler.Bind(&with_constructor);
350 bound_function_map.Bind(assembler.LoadContextElement(
351 native_context, Context::BOUND_FUNCTION_WITH_CONSTRUCTOR_MAP_INDEX));
352 assembler.Goto(&map_done);
353
354 assembler.Bind(&map_done);
355
356 // Verify that __proto__ matches that of a the target bound function.
357 assembler.Comment("Verify that __proto__ matches target bound function");
358 Node* prototype = assembler.LoadMapPrototype(receiver_map);
359 Node* expected_prototype =
360 assembler.LoadMapPrototype(bound_function_map.value());
361 assembler.GotoIf(assembler.WordNotEqual(prototype, expected_prototype),
362 &slow);
363
364 // Allocate the arguments array.
365 assembler.Comment("Allocate the arguments array");
366 Variable argument_array(&assembler, MachineRepresentation::kTagged);
367 Label empty_arguments(&assembler);
368 Label arguments_done(&assembler, &argument_array);
369 assembler.GotoIf(
370 assembler.UintPtrLessThanOrEqual(argc, assembler.IntPtrConstant(1)),
371 &empty_arguments);
372 Node* elements_length =
373 assembler.IntPtrSub(argc, assembler.IntPtrConstant(1));
374 Node* elements = assembler.AllocateFixedArray(
375 FAST_ELEMENTS, elements_length, CodeStubAssembler::INTPTR_PARAMETERS);
376 Variable index(&assembler, MachineType::PointerRepresentation());
377 index.Bind(assembler.IntPtrConstant(0));
378 CodeStubAssembler::VariableList foreach_vars({&index}, assembler.zone());
379 args.ForEach(
380 foreach_vars,
381 [elements, &index](CodeStubAssembler* assembler, compiler::Node* arg) {
382 assembler->StoreFixedArrayElement(elements, index.value(), arg,
383 UPDATE_WRITE_BARRIER, 0,
384 CodeStubAssembler::INTPTR_PARAMETERS);
385 assembler->Increment(index);
386 },
387 assembler.IntPtrConstant(1));
388 argument_array.Bind(elements);
389 assembler.Goto(&arguments_done);
390
391 assembler.Bind(&empty_arguments);
392 argument_array.Bind(assembler.EmptyFixedArrayConstant());
393 assembler.Goto(&arguments_done);
394
395 assembler.Bind(&arguments_done);
396
397 // Determine bound receiver.
398 assembler.Comment("Determine bound receiver");
399 Variable bound_receiver(&assembler, MachineRepresentation::kTagged);
400 Label has_receiver(&assembler);
401 Label receiver_done(&assembler, &bound_receiver);
402 assembler.GotoIf(assembler.WordNotEqual(argc, assembler.IntPtrConstant(0)),
403 &has_receiver);
404 bound_receiver.Bind(assembler.UndefinedConstant());
405 assembler.Goto(&receiver_done);
406
407 assembler.Bind(&has_receiver);
408 bound_receiver.Bind(args.AtIndex(0));
409 assembler.Goto(&receiver_done);
410
411 assembler.Bind(&receiver_done);
412
413 // Allocate the resulting bound function.
414 assembler.Comment("Allocate the resulting bound function");
415 Node* bound_function = assembler.Allocate(JSBoundFunction::kSize);
416 assembler.StoreMapNoWriteBarrier(bound_function, bound_function_map.value());
417 assembler.StoreObjectFieldNoWriteBarrier(
418 bound_function, JSBoundFunction::kBoundTargetFunctionOffset, receiver);
419 assembler.StoreObjectFieldNoWriteBarrier(bound_function,
420 JSBoundFunction::kBoundThisOffset,
421 bound_receiver.value());
422 assembler.StoreObjectFieldNoWriteBarrier(
423 bound_function, JSBoundFunction::kBoundArgumentsOffset,
424 argument_array.value());
425 Node* empty_fixed_array = assembler.EmptyFixedArrayConstant();
426 assembler.StoreObjectFieldNoWriteBarrier(
427 bound_function, JSObject::kPropertiesOffset, empty_fixed_array);
428 assembler.StoreObjectFieldNoWriteBarrier(
429 bound_function, JSObject::kElementsOffset, empty_fixed_array);
430
431 args.PopAndReturn(bound_function);
432 assembler.Bind(&slow);
433
434 Node* target = assembler.LoadFromFrame(
435 StandardFrameConstants::kFunctionOffset, MachineType::TaggedPointer());
436 assembler.TailCallStub(
437 CodeFactory::FunctionPrototypeBind(assembler.isolate()), context, target,
438 new_target, argc);
439 }
440
258 // TODO(verwaest): This is a temporary helper until the FastFunctionBind stub 441 // TODO(verwaest): This is a temporary helper until the FastFunctionBind stub
259 // can tailcall to the builtin directly. 442 // can tailcall to the builtin directly.
260 RUNTIME_FUNCTION(Runtime_FunctionBind) { 443 RUNTIME_FUNCTION(Runtime_FunctionBind) {
261 DCHECK_EQ(2, args.length()); 444 DCHECK_EQ(2, args.length());
262 Arguments* incoming = reinterpret_cast<Arguments*>(args[0]); 445 Arguments* incoming = reinterpret_cast<Arguments*>(args[0]);
263 // Rewrap the arguments as builtins arguments. 446 // Rewrap the arguments as builtins arguments.
264 int argc = incoming->length() + BuiltinArguments::kNumExtraArgsWithReceiver; 447 int argc = incoming->length() + BuiltinArguments::kNumExtraArgsWithReceiver;
265 BuiltinArguments caller_args(argc, incoming->arguments() + 1); 448 BuiltinArguments caller_args(argc, incoming->arguments() + 1);
266 return DoFunctionBind(isolate, caller_args); 449 return DoFunctionBind(isolate, caller_args);
267 } 450 }
(...skipping 21 matching lines...) Expand all
289 472
290 Node* f = assembler.Parameter(0); 473 Node* f = assembler.Parameter(0);
291 Node* v = assembler.Parameter(1); 474 Node* v = assembler.Parameter(1);
292 Node* context = assembler.Parameter(4); 475 Node* context = assembler.Parameter(4);
293 Node* result = assembler.OrdinaryHasInstance(context, f, v); 476 Node* result = assembler.OrdinaryHasInstance(context, f, v);
294 assembler.Return(result); 477 assembler.Return(result);
295 } 478 }
296 479
297 } // namespace internal 480 } // namespace internal
298 } // namespace v8 481 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins-array.cc ('k') | src/code-factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698