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

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

Issue 2146293003: [builtins] implement Array.prototype.includes in TurboFan (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fixit Created 4 years, 5 months 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
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/builtins/builtins.h" 5 #include "src/builtins/builtins.h"
6 6
7 #include "src/api-arguments.h" 7 #include "src/api-arguments.h"
8 #include "src/api-natives.h" 8 #include "src/api-natives.h"
9 #include "src/api.h" 9 #include "src/api.h"
10 #include "src/base/ieee754.h" 10 #include "src/base/ieee754.h"
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 assembler->Return(assembler->BooleanConstant(true)); 336 assembler->Return(assembler->BooleanConstant(true));
337 337
338 assembler->Bind(&return_false); 338 assembler->Bind(&return_false);
339 assembler->Return(assembler->BooleanConstant(false)); 339 assembler->Return(assembler->BooleanConstant(false));
340 340
341 assembler->Bind(&call_runtime); 341 assembler->Bind(&call_runtime);
342 assembler->Return( 342 assembler->Return(
343 assembler->CallRuntime(Runtime::kArrayIsArray, context, object)); 343 assembler->CallRuntime(Runtime::kArrayIsArray, context, object));
344 } 344 }
345 345
346 void Builtins::Generate_ArrayIncludes(CodeStubAssembler* assembler) {
347 typedef compiler::Node Node;
348 typedef CodeStubAssembler::Label Label;
349 typedef CodeStubAssembler::Variable Variable;
350
351 Node* array = assembler->Parameter(0);
352 Node* search_element = assembler->Parameter(1);
353 Node* start_from = assembler->Parameter(2);
354 Node* context = assembler->Parameter(3 + 2);
355
356 Node* int32_zero = assembler->Int32Constant(0);
357 Node* int32_one = assembler->Int32Constant(1);
358
359 Variable len(assembler, MachineRepresentation::kWord32),
360 k(assembler, MachineRepresentation::kWord32),
361 n(assembler, MachineRepresentation::kWord32);
362
363 Label init_k(assembler), return_true(assembler), return_false(assembler),
364 call_runtime(assembler);
365
366 { // Prologue
367 // 1. Bailout to slow path if `array` is not a JSArray
368 assembler->GotoIf(assembler->WordIsSmi(array), &call_runtime);
369 Node* instance_type = assembler->LoadInstanceType(array);
370 assembler->GotoUnless(
371 assembler->Word32Equal(instance_type,
372 assembler->Int32Constant(JS_ARRAY_TYPE)),
373 &call_runtime);
374
375 // 2. Bailout to slow path if elements kind is not fast
376 Node* map = assembler->LoadMap(array);
377 Node* bit_field2 = assembler->LoadMapBitField2(map);
378 Node* elements_kind =
379 assembler->BitFieldDecode<Map::ElementsKindBits>(bit_field2);
380 assembler->GotoIf(
381 assembler->Int32GreaterThan(
382 elements_kind, assembler->Int32Constant(LAST_FAST_ELEMENTS_KIND)),
383 &call_runtime);
384
385 // 3. Bailout to slow path if array protector field invalid
386 assembler->GotoUnless(
387 assembler->WordEqual(
388 assembler->LoadObjectField(
389 assembler->LoadRoot(Heap::kArrayProtectorRootIndex),
390 PropertyCell::kValueOffset),
391 assembler->SmiConstant(
392 Smi::FromInt(Isolate::kArrayProtectorValid))),
393 &call_runtime);
394
395 len.Bind(assembler->SmiToWord(
396 assembler->LoadObjectField(array, JSArray::kLengthOffset)));
397 assembler->GotoUnless(assembler->Word32Equal(len.value(), int32_zero),
398 &init_k);
399 assembler->Return(assembler->BooleanConstant(false));
400 }
401
402 assembler->Bind(&init_k);
403 {
404 Variable tagged_n(assembler, MachineRepresentation::kTagged);
405 Label done(assembler), if_neg(assembler), init_k_smi(assembler),
406 init_k_zero(assembler);
407 Callable call_to_integer = CodeFactory::ToInteger(assembler->isolate());
408 tagged_n.Bind(assembler->CallStub(call_to_integer, context, start_from));
409
410 assembler->GotoIf(assembler->WordIsSmi(tagged_n.value()), &init_k_smi);
411
412 Node* fp_len = assembler->ChangeInt32ToFloat64(len.value());
413 Node* fp_n = assembler->TruncateTaggedToFloat64(context, tagged_n.value());
414
415 assembler->GotoIf(assembler->Float64GreaterThanOrEqual(fp_n, fp_len),
416 &return_false);
417
418 tagged_n.Bind(
419 assembler->SmiFromWord32(assembler->TruncateFloat64ToWord32(fp_n)));
420
421 assembler->Goto(&init_k_smi);
422 assembler->Bind(&init_k_smi);
423 n.Bind(assembler->SmiToWord32(tagged_n.value()));
424
425 assembler->GotoUnless(
426 assembler->Int32GreaterThanOrEqual(n.value(), int32_zero), &if_neg);
427 k.Bind(n.value());
428 assembler->Goto(&done);
429
430 assembler->Bind(&if_neg);
431 k.Bind(assembler->Int32Add(len.value(), n.value()));
432 assembler->BranchIf(assembler->Int32LessThan(k.value(), int32_zero),
433 &init_k_zero, &done);
434
435 assembler->Bind(&init_k_zero);
436 k.Bind(int32_zero);
437
438 assembler->Goto(&done);
439 assembler->Bind(&done);
440 }
441
442 { // Repeat while k < len
443 Variable element_k(assembler, MachineRepresentation::kTagged);
444 Variable stable(assembler, MachineRepresentation::kWord32);
445
446 Variable* loop_body_variables[] = {&k, &stable};
447
448 Label loop_body(assembler, 2,
Benedikt Meurer 2016/07/15 17:59:55 You really want one really tight loop per elements
caitp 2016/07/15 22:11:17 This is a good idea, but currently this is not sou
Benedikt Meurer 2016/07/16 12:40:27 Ah indeed, you also need to check that the prototy
449 static_cast<Variable **>(loop_body_variables)),
450 continue_loop(assembler), if_issmiorobject(assembler),
451 if_isdouble(assembler), if_slowpath(assembler), test_element(assembler);
452
453 stable.Bind(int32_one);
454 Node* map = assembler->LoadMap(array);
455 Node* bit_field2 = assembler->LoadMapBitField2(map);
456 Node* elements_kind =
457 assembler->BitFieldDecode<Map::ElementsKindBits>(bit_field2);
458
459 assembler->Goto(&loop_body);
460 assembler->Bind(&loop_body);
461
462 assembler->GotoUnless(assembler->Uint32LessThan(k.value(), len.value()),
463 &return_false);
464
465 assembler->GotoIf(assembler->WordEqual(stable.value(), int32_zero),
466 &if_slowpath);
467
468 assembler->Branch(
469 assembler->Int32LessThan(
470 elements_kind, assembler->Int32Constant(FAST_DOUBLE_ELEMENTS)),
471 &if_issmiorobject, &if_isdouble);
472
473 assembler->Bind(&if_issmiorobject);
474 { // Fast Smi/Object elements
475 Node* elements = assembler->LoadElements(array);
476 Node* length = assembler->LoadFixedArrayBaseLength(elements);
477
478 assembler->GotoUnless(
479 assembler->Int32LessThan(k.value(), assembler->SmiToWord32(length)),
480 &if_slowpath);
481
482 Node* element = assembler->LoadFixedArrayElement(elements, k.value());
483 Node* the_hole = assembler->TheHoleConstant();
484
485 assembler->GotoUnless(assembler->WordNotEqual(element, the_hole),
486 &if_slowpath);
Benedikt Meurer 2016/07/15 17:59:55 You can just turn the hole into undefined, since y
caitp 2016/07/15 22:11:17 I'm not sure, we still end up on the fast path wit
Benedikt Meurer 2016/07/16 12:40:27 As mentioned above, indexed accessors in the proto
487 element_k.Bind(element);
488 assembler->Goto(&test_element);
489 }
490
491 assembler->Bind(&if_isdouble);
492 { // Fast double elements
493 Node* elements = assembler->LoadElements(array);
494 Node* length = assembler->LoadFixedArrayBaseLength(elements);
495
496 assembler->GotoUnless(
497 assembler->Int32LessThan(k.value(), assembler->SmiToWord32(length)),
498 &if_slowpath);
499
500 if (kPointerSize == kDoubleSize) {
501 Node* element = assembler->LoadFixedDoubleArrayElement(
502 elements, k.value(), MachineType::Uint64());
503 Node* the_hole = assembler->Int64Constant(kHoleNanInt64);
504 assembler->GotoIf(assembler->Word64Equal(element, the_hole),
505 &if_slowpath);
506 } else {
507 Node* element_upper = assembler->LoadFixedDoubleArrayElement(
508 elements, k.value(), MachineType::Uint32(),
509 kIeeeDoubleExponentWordOffset);
510 assembler->GotoIf(
511 assembler->Word32Equal(element_upper,
512 assembler->Int32Constant(kHoleNanUpper32)),
513 &if_slowpath);
514 }
515
516 Node* element = assembler->LoadFixedDoubleArrayElement(
517 elements, k.value(), MachineType::Float64());
518 element_k.Bind(assembler->AllocateHeapNumberWithValue(element));
519 assembler->Goto(&test_element);
520 }
521
522 assembler->Bind(&if_slowpath);
523 {
524 Node* element =
525 assembler->CallRuntime(Runtime::kGetProperty, context, array,
526 assembler->SmiFromWord32(k.value()));
527 element_k.Bind(element);
528
529 // Slow path may have modified elements backing store in some way.
530 assembler->GotoIf(assembler->WordEqual(stable.value(), int32_zero),
531 &test_element);
532 Node* current_map = assembler->LoadMap(array);
533 assembler->GotoIf(assembler->WordEqual(map, current_map), &test_element);
534 stable.Bind(int32_zero);
535 assembler->Goto(&test_element);
536 }
537
538 assembler->Bind(&test_element);
539 assembler->BranchIfSameValueZero(search_element, element_k.value(), context,
540 &return_true, &continue_loop);
541
542 assembler->Bind(&continue_loop);
543 k.Bind(assembler->Int32Add(k.value(), int32_one));
544 assembler->Goto(&loop_body);
545 }
546
547 assembler->Bind(&return_true);
548 assembler->Return(assembler->BooleanConstant(true));
549
550 assembler->Bind(&return_false);
551 assembler->Return(assembler->BooleanConstant(false));
552
553 assembler->Bind(&call_runtime);
554 assembler->Return(assembler->CallRuntime(Runtime::kArrayIncludes_Slow,
555 context, array, search_element,
556 start_from));
557 }
558
346 void Builtins::Generate_ObjectHasOwnProperty(CodeStubAssembler* assembler) { 559 void Builtins::Generate_ObjectHasOwnProperty(CodeStubAssembler* assembler) {
347 typedef compiler::Node Node; 560 typedef compiler::Node Node;
348 typedef CodeStubAssembler::Label Label; 561 typedef CodeStubAssembler::Label Label;
349 typedef CodeStubAssembler::Variable Variable; 562 typedef CodeStubAssembler::Variable Variable;
350 563
351 Node* object = assembler->Parameter(0); 564 Node* object = assembler->Parameter(0);
352 Node* key = assembler->Parameter(1); 565 Node* key = assembler->Parameter(1);
353 Node* context = assembler->Parameter(4); 566 Node* context = assembler->Parameter(4);
354 567
355 Label call_runtime(assembler), return_true(assembler), 568 Label call_runtime(assembler), return_true(assembler),
(...skipping 6469 matching lines...) Expand 10 before | Expand all | Expand 10 after
6825 #define DEFINE_BUILTIN_ACCESSOR(Name, ...) \ 7038 #define DEFINE_BUILTIN_ACCESSOR(Name, ...) \
6826 Handle<Code> Builtins::Name() { \ 7039 Handle<Code> Builtins::Name() { \
6827 Code** code_address = reinterpret_cast<Code**>(builtin_address(k##Name)); \ 7040 Code** code_address = reinterpret_cast<Code**>(builtin_address(k##Name)); \
6828 return Handle<Code>(code_address); \ 7041 return Handle<Code>(code_address); \
6829 } 7042 }
6830 BUILTIN_LIST_ALL(DEFINE_BUILTIN_ACCESSOR) 7043 BUILTIN_LIST_ALL(DEFINE_BUILTIN_ACCESSOR)
6831 #undef DEFINE_BUILTIN_ACCESSOR 7044 #undef DEFINE_BUILTIN_ACCESSOR
6832 7045
6833 } // namespace internal 7046 } // namespace internal
6834 } // namespace v8 7047 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins.h ('k') | src/code-stub-assembler.h » ('j') | src/code-stub-assembler.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698