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

Side by Side Diff: src/code-stubs-hydrogen.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/code-stubs.h ('k') | src/ia32/code-stubs-ia32.cc » ('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 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 "src/code-stubs.h" 5 #include "src/code-stubs.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "src/bailout-reason.h" 9 #include "src/bailout-reason.h"
10 #include "src/code-factory.h" 10 #include "src/code-factory.h"
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after
369 { 369 {
370 HValue* argument = Add<HAccessArgumentsAt>(argument_elements, argc, key); 370 HValue* argument = Add<HAccessArgumentsAt>(argument_elements, argc, key);
371 HValue* index = AddUncasted<HAdd>(key, length); 371 HValue* index = AddUncasted<HAdd>(key, length);
372 AddElementAccess(elements, index, argument, object, nullptr, kind, STORE); 372 AddElementAccess(elements, index, argument, object, nullptr, kind, STORE);
373 } 373 }
374 builder.EndBody(); 374 builder.EndBody();
375 return new_length; 375 return new_length;
376 } 376 }
377 377
378 template <> 378 template <>
379 HValue* CodeStubGraphBuilder<FastFunctionBindStub>::BuildCodeStub() {
380 // TODO(verwaest): Fix deoptimizer messages.
381 HValue* argc = GetArgumentsLength();
382 HInstruction* argument_elements = Add<HArgumentsElements>(false, false);
383 HInstruction* object = Add<HAccessArgumentsAt>(argument_elements, argc,
384 graph()->GetConstantMinus1());
385 BuildCheckHeapObject(object);
386 HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap());
387 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_JS_FUNCTION);
388
389 // Disallow binding of slow-mode functions. We need to figure out whether the
390 // length and name property are in the original state.
391 {
392 HValue* bit_field3 =
393 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField3());
394 HValue* mask = Add<HConstant>(static_cast<int>(Map::DictionaryMap::kMask));
395 HValue* bit = AddUncasted<HBitwise>(Token::BIT_AND, bit_field3, mask);
396 IfBuilder check(this);
397 check.If<HCompareNumericAndBranch>(bit, mask, Token::EQ);
398 check.ThenDeopt(DeoptimizeReason::kFastPathFailed);
399 check.End();
400 }
401
402 // Check whether the length and name properties are still present as
403 // AccessorInfo objects. In that case, their value can be recomputed even if
404 // the actual value on the object changes.
405 {
406 HValue* descriptors =
407 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapDescriptors());
408
409 HValue* descriptors_length = Add<HLoadNamedField>(
410 descriptors, nullptr, HObjectAccess::ForFixedArrayLength());
411 IfBuilder range(this);
412 range.If<HCompareNumericAndBranch>(descriptors_length,
413 graph()->GetConstant1(), Token::LTE);
414 range.ThenDeopt(DeoptimizeReason::kFastPathFailed);
415 range.End();
416
417 // Verify .length.
418 const int length_index = JSFunction::kLengthDescriptorIndex;
419 HValue* maybe_length = Add<HLoadKeyed>(
420 descriptors, Add<HConstant>(DescriptorArray::ToKeyIndex(length_index)),
421 nullptr, nullptr, FAST_ELEMENTS);
422 Unique<Name> length_string = Unique<Name>::CreateUninitialized(
423 isolate()->factory()->length_string());
424 Add<HCheckValue>(maybe_length, length_string, false);
425
426 HValue* maybe_length_accessor = Add<HLoadKeyed>(
427 descriptors,
428 Add<HConstant>(DescriptorArray::ToValueIndex(length_index)), nullptr,
429 nullptr, FAST_ELEMENTS);
430 BuildCheckHeapObject(maybe_length_accessor);
431 Add<HCheckMaps>(maybe_length_accessor,
432 isolate()->factory()->accessor_info_map());
433
434 // Verify .name.
435 const int name_index = JSFunction::kNameDescriptorIndex;
436 HValue* maybe_name = Add<HLoadKeyed>(
437 descriptors, Add<HConstant>(DescriptorArray::ToKeyIndex(name_index)),
438 nullptr, nullptr, FAST_ELEMENTS);
439 Unique<Name> name_string =
440 Unique<Name>::CreateUninitialized(isolate()->factory()->name_string());
441 Add<HCheckValue>(maybe_name, name_string, false);
442
443 HValue* maybe_name_accessor = Add<HLoadKeyed>(
444 descriptors, Add<HConstant>(DescriptorArray::ToValueIndex(name_index)),
445 nullptr, nullptr, FAST_ELEMENTS);
446 BuildCheckHeapObject(maybe_name_accessor);
447 Add<HCheckMaps>(maybe_name_accessor,
448 isolate()->factory()->accessor_info_map());
449 }
450
451 // Choose the right bound function map based on whether the target is
452 // constructable.
453 {
454 HValue* bit_field =
455 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField());
456 HValue* mask = Add<HConstant>(static_cast<int>(1 << Map::kIsConstructor));
457 HValue* bits = AddUncasted<HBitwise>(Token::BIT_AND, bit_field, mask);
458
459 HValue* native_context = BuildGetNativeContext();
460 IfBuilder is_constructor(this);
461 is_constructor.If<HCompareNumericAndBranch>(bits, mask, Token::EQ);
462 is_constructor.Then();
463 {
464 HValue* map = Add<HLoadNamedField>(
465 native_context, nullptr,
466 HObjectAccess::ForContextSlot(
467 Context::BOUND_FUNCTION_WITH_CONSTRUCTOR_MAP_INDEX));
468 environment()->Push(map);
469 }
470 is_constructor.Else();
471 {
472 HValue* map = Add<HLoadNamedField>(
473 native_context, nullptr,
474 HObjectAccess::ForContextSlot(
475 Context::BOUND_FUNCTION_WITHOUT_CONSTRUCTOR_MAP_INDEX));
476 environment()->Push(map);
477 }
478 is_constructor.End();
479 }
480 HValue* bound_function_map = environment()->Pop();
481
482 // Verify that __proto__ matches that of a the target bound function.
483 {
484 HValue* prototype =
485 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForPrototype());
486 HValue* expected_prototype = Add<HLoadNamedField>(
487 bound_function_map, nullptr, HObjectAccess::ForPrototype());
488 IfBuilder equal_prototype(this);
489 equal_prototype.IfNot<HCompareObjectEqAndBranch>(prototype,
490 expected_prototype);
491 equal_prototype.ThenDeopt(DeoptimizeReason::kFastPathFailed);
492 equal_prototype.End();
493 }
494
495 // Allocate the arguments array.
496 IfBuilder empty_args(this);
497 empty_args.If<HCompareNumericAndBranch>(argc, graph()->GetConstant1(),
498 Token::LTE);
499 empty_args.Then();
500 { environment()->Push(Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex)); }
501 empty_args.Else();
502 {
503 HValue* elements_length = AddUncasted<HSub>(argc, graph()->GetConstant1());
504 HValue* elements =
505 BuildAllocateAndInitializeArray(FAST_ELEMENTS, elements_length);
506
507 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
508 HValue* start = graph()->GetConstant1();
509 HValue* key = builder.BeginBody(start, argc, Token::LT);
510 {
511 HValue* argument = Add<HAccessArgumentsAt>(argument_elements, argc, key);
512 HValue* index = AddUncasted<HSub>(key, graph()->GetConstant1());
513 AddElementAccess(elements, index, argument, elements, nullptr,
514 FAST_ELEMENTS, STORE);
515 }
516 builder.EndBody();
517 environment()->Push(elements);
518 }
519 empty_args.End();
520 HValue* elements = environment()->Pop();
521
522 // Find the 'this' to bind.
523 IfBuilder no_receiver(this);
524 no_receiver.If<HCompareNumericAndBranch>(argc, graph()->GetConstant0(),
525 Token::EQ);
526 no_receiver.Then();
527 { environment()->Push(Add<HLoadRoot>(Heap::kUndefinedValueRootIndex)); }
528 no_receiver.Else();
529 {
530 environment()->Push(Add<HAccessArgumentsAt>(argument_elements, argc,
531 graph()->GetConstant0()));
532 }
533 no_receiver.End();
534 HValue* receiver = environment()->Pop();
535
536 // Allocate the resulting bound function.
537 HValue* size = Add<HConstant>(JSBoundFunction::kSize);
538 HValue* bound_function =
539 Add<HAllocate>(size, HType::JSObject(), NOT_TENURED,
540 JS_BOUND_FUNCTION_TYPE, graph()->GetConstant0());
541 Add<HStoreNamedField>(bound_function, HObjectAccess::ForMap(),
542 bound_function_map);
543 HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
544 Add<HStoreNamedField>(bound_function, HObjectAccess::ForPropertiesPointer(),
545 empty_fixed_array);
546 Add<HStoreNamedField>(bound_function, HObjectAccess::ForElementsPointer(),
547 empty_fixed_array);
548 Add<HStoreNamedField>(bound_function, HObjectAccess::ForBoundTargetFunction(),
549 object);
550
551 Add<HStoreNamedField>(bound_function, HObjectAccess::ForBoundThis(),
552 receiver);
553 Add<HStoreNamedField>(bound_function, HObjectAccess::ForBoundArguments(),
554 elements);
555
556 return bound_function;
557 }
558
559 Handle<Code> FastFunctionBindStub::GenerateCode() {
560 return DoGenerateCode(this);
561 }
562
563 template <>
564 HValue* CodeStubGraphBuilder<LoadFastElementStub>::BuildCodeStub() { 379 HValue* CodeStubGraphBuilder<LoadFastElementStub>::BuildCodeStub() {
565 LoadKeyedHoleMode hole_mode = casted_stub()->convert_hole_to_undefined() 380 LoadKeyedHoleMode hole_mode = casted_stub()->convert_hole_to_undefined()
566 ? CONVERT_HOLE_TO_UNDEFINED 381 ? CONVERT_HOLE_TO_UNDEFINED
567 : NEVER_RETURN_HOLE; 382 : NEVER_RETURN_HOLE;
568 383
569 HInstruction* load = BuildUncheckedMonomorphicElementAccess( 384 HInstruction* load = BuildUncheckedMonomorphicElementAccess(
570 GetParameter(Descriptor::kReceiver), GetParameter(Descriptor::kName), 385 GetParameter(Descriptor::kReceiver), GetParameter(Descriptor::kName),
571 NULL, casted_stub()->is_js_array(), casted_stub()->elements_kind(), LOAD, 386 NULL, casted_stub()->is_js_array(), casted_stub()->elements_kind(), LOAD,
572 hole_mode, STANDARD_STORE); 387 hole_mode, STANDARD_STORE);
573 return load; 388 return load;
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after
997 return BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash); 812 return BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash);
998 } 813 }
999 814
1000 815
1001 Handle<Code> LoadDictionaryElementStub::GenerateCode() { 816 Handle<Code> LoadDictionaryElementStub::GenerateCode() {
1002 return DoGenerateCode(this); 817 return DoGenerateCode(this);
1003 } 818 }
1004 819
1005 } // namespace internal 820 } // namespace internal
1006 } // namespace v8 821 } // namespace v8
OLDNEW
« no previous file with comments | « src/code-stubs.h ('k') | src/ia32/code-stubs-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698