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

Side by Side Diff: src/code-stubs-hydrogen.cc

Issue 2497243002: [stubs] Port builtin for Array.push fast-case from Crankshaft to TF (Closed)
Patch Set: Fix GC mole 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<FastArrayPushStub>::BuildCodeStub() {
380 // TODO(verwaest): Fix deoptimizer messages.
381 HValue* argc = GetArgumentsLength();
382
383 HInstruction* argument_elements = Add<HArgumentsElements>(false, false);
384 HInstruction* object = Add<HAccessArgumentsAt>(argument_elements, argc,
385 graph()->GetConstantMinus1());
386 BuildCheckHeapObject(object);
387 HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap());
388 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_JS_ARRAY);
389
390 // Disallow pushing onto prototypes. It might be the JSArray prototype.
391 // Disallow pushing onto non-extensible objects.
392 {
393 HValue* bit_field2 =
394 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField2());
395 HValue* mask =
396 Add<HConstant>(static_cast<int>(Map::IsPrototypeMapBits::kMask) |
397 (1 << Map::kIsExtensible));
398 HValue* bits = AddUncasted<HBitwise>(Token::BIT_AND, bit_field2, mask);
399 IfBuilder check(this);
400 check.If<HCompareNumericAndBranch>(
401 bits, Add<HConstant>(1 << Map::kIsExtensible), Token::NE);
402 check.ThenDeopt(DeoptimizeReason::kFastPathFailed);
403 check.End();
404 }
405
406 // Disallow pushing onto arrays in dictionary named property mode. We need to
407 // figure out whether the length property is still writable.
408 {
409 HValue* bit_field3 =
410 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField3());
411 HValue* mask = Add<HConstant>(static_cast<int>(Map::DictionaryMap::kMask));
412 HValue* bit = AddUncasted<HBitwise>(Token::BIT_AND, bit_field3, mask);
413 IfBuilder check(this);
414 check.If<HCompareNumericAndBranch>(bit, mask, Token::EQ);
415 check.ThenDeopt(DeoptimizeReason::kFastPathFailed);
416 check.End();
417 }
418
419 // Check whether the length property is writable. The length property is the
420 // only default named property on arrays. It's nonconfigurable, hence is
421 // guaranteed to stay the first property.
422 {
423 HValue* descriptors =
424 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapDescriptors());
425 HValue* details = Add<HLoadKeyed>(
426 descriptors, Add<HConstant>(DescriptorArray::ToDetailsIndex(0)),
427 nullptr, nullptr, FAST_SMI_ELEMENTS);
428 HValue* mask =
429 Add<HConstant>(READ_ONLY << PropertyDetails::AttributesField::kShift);
430 HValue* bit = AddUncasted<HBitwise>(Token::BIT_AND, details, mask);
431 IfBuilder readonly(this);
432 readonly.If<HCompareNumericAndBranch>(bit, mask, Token::EQ);
433 readonly.ThenDeopt(DeoptimizeReason::kFastPathFailed);
434 readonly.End();
435 }
436
437 HValue* null = Add<HLoadRoot>(Heap::kNullValueRootIndex);
438 HValue* empty = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
439 environment()->Push(map);
440 LoopBuilder check_prototypes(this);
441 check_prototypes.BeginBody(1);
442 {
443 HValue* parent_map = environment()->Pop();
444 HValue* prototype = Add<HLoadNamedField>(parent_map, nullptr,
445 HObjectAccess::ForPrototype());
446
447 IfBuilder is_null(this);
448 is_null.If<HCompareObjectEqAndBranch>(prototype, null);
449 is_null.Then();
450 check_prototypes.Break();
451 is_null.End();
452
453 HValue* prototype_map =
454 Add<HLoadNamedField>(prototype, nullptr, HObjectAccess::ForMap());
455 HValue* instance_type = Add<HLoadNamedField>(
456 prototype_map, nullptr, HObjectAccess::ForMapInstanceType());
457 IfBuilder check_instance_type(this);
458 check_instance_type.If<HCompareNumericAndBranch>(
459 instance_type, Add<HConstant>(LAST_CUSTOM_ELEMENTS_RECEIVER),
460 Token::LTE);
461 check_instance_type.ThenDeopt(DeoptimizeReason::kFastPathFailed);
462 check_instance_type.End();
463
464 HValue* elements = Add<HLoadNamedField>(
465 prototype, nullptr, HObjectAccess::ForElementsPointer());
466 IfBuilder no_elements(this);
467 no_elements.IfNot<HCompareObjectEqAndBranch>(elements, empty);
468 no_elements.ThenDeopt(DeoptimizeReason::kFastPathFailed);
469 no_elements.End();
470
471 environment()->Push(prototype_map);
472 }
473 check_prototypes.EndBody();
474
475 HValue* bit_field2 =
476 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField2());
477 HValue* kind = BuildDecodeField<Map::ElementsKindBits>(bit_field2);
478
479 // Below we only check the upper bound of the relevant ranges to include both
480 // holey and non-holey versions. We check them in order smi, object, double
481 // since smi < object < double.
482 STATIC_ASSERT(FAST_SMI_ELEMENTS < FAST_HOLEY_SMI_ELEMENTS);
483 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS < FAST_HOLEY_ELEMENTS);
484 STATIC_ASSERT(FAST_ELEMENTS < FAST_HOLEY_ELEMENTS);
485 STATIC_ASSERT(FAST_HOLEY_ELEMENTS < FAST_HOLEY_DOUBLE_ELEMENTS);
486 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FAST_HOLEY_DOUBLE_ELEMENTS);
487 IfBuilder has_smi_elements(this);
488 has_smi_elements.If<HCompareNumericAndBranch>(
489 kind, Add<HConstant>(FAST_HOLEY_SMI_ELEMENTS), Token::LTE);
490 has_smi_elements.Then();
491 {
492 HValue* new_length = BuildPushElement(object, argc, argument_elements,
493 FAST_HOLEY_SMI_ELEMENTS);
494 environment()->Push(new_length);
495 }
496 has_smi_elements.Else();
497 {
498 IfBuilder has_object_elements(this);
499 has_object_elements.If<HCompareNumericAndBranch>(
500 kind, Add<HConstant>(FAST_HOLEY_ELEMENTS), Token::LTE);
501 has_object_elements.Then();
502 {
503 HValue* new_length = BuildPushElement(object, argc, argument_elements,
504 FAST_HOLEY_ELEMENTS);
505 environment()->Push(new_length);
506 }
507 has_object_elements.Else();
508 {
509 IfBuilder has_double_elements(this);
510 has_double_elements.If<HCompareNumericAndBranch>(
511 kind, Add<HConstant>(FAST_HOLEY_DOUBLE_ELEMENTS), Token::LTE);
512 has_double_elements.Then();
513 {
514 HValue* new_length = BuildPushElement(object, argc, argument_elements,
515 FAST_HOLEY_DOUBLE_ELEMENTS);
516 environment()->Push(new_length);
517 }
518 has_double_elements.ElseDeopt(DeoptimizeReason::kFastPathFailed);
519 has_double_elements.End();
520 }
521 has_object_elements.End();
522 }
523 has_smi_elements.End();
524
525 return environment()->Pop();
526 }
527
528 Handle<Code> FastArrayPushStub::GenerateCode() { return DoGenerateCode(this); }
529
530 template <>
531 HValue* CodeStubGraphBuilder<FastFunctionBindStub>::BuildCodeStub() { 379 HValue* CodeStubGraphBuilder<FastFunctionBindStub>::BuildCodeStub() {
532 // TODO(verwaest): Fix deoptimizer messages. 380 // TODO(verwaest): Fix deoptimizer messages.
533 HValue* argc = GetArgumentsLength(); 381 HValue* argc = GetArgumentsLength();
534 HInstruction* argument_elements = Add<HArgumentsElements>(false, false); 382 HInstruction* argument_elements = Add<HArgumentsElements>(false, false);
535 HInstruction* object = Add<HAccessArgumentsAt>(argument_elements, argc, 383 HInstruction* object = Add<HAccessArgumentsAt>(argument_elements, argc,
536 graph()->GetConstantMinus1()); 384 graph()->GetConstantMinus1());
537 BuildCheckHeapObject(object); 385 BuildCheckHeapObject(object);
538 HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap()); 386 HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap());
539 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_JS_FUNCTION); 387 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_JS_FUNCTION);
540 388
(...skipping 608 matching lines...) Expand 10 before | Expand all | Expand 10 after
1149 return BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash); 997 return BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash);
1150 } 998 }
1151 999
1152 1000
1153 Handle<Code> LoadDictionaryElementStub::GenerateCode() { 1001 Handle<Code> LoadDictionaryElementStub::GenerateCode() {
1154 return DoGenerateCode(this); 1002 return DoGenerateCode(this);
1155 } 1003 }
1156 1004
1157 } // namespace internal 1005 } // namespace internal
1158 } // namespace v8 1006 } // 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