Chromium Code Reviews

Side by Side Diff: src/builtins.cc

Issue 1843613002: Add initial code-stub version of Object.prototype.hasOwnProperty (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
« no previous file with comments | « src/builtins.h ('k') | src/compiler/code-stub-assembler.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 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.h" 5 #include "src/builtins.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/api-arguments.h" 8 #include "src/api-arguments.h"
9 #include "src/api-natives.h" 9 #include "src/api-natives.h"
10 #include "src/base/once.h" 10 #include "src/base/once.h"
(...skipping 326 matching lines...)
337 337
338 338
339 BUILTIN(Illegal) { 339 BUILTIN(Illegal) {
340 UNREACHABLE(); 340 UNREACHABLE();
341 return isolate->heap()->undefined_value(); // Make compiler happy. 341 return isolate->heap()->undefined_value(); // Make compiler happy.
342 } 342 }
343 343
344 344
345 BUILTIN(EmptyFunction) { return isolate->heap()->undefined_value(); } 345 BUILTIN(EmptyFunction) { return isolate->heap()->undefined_value(); }
346 346
347 // ES6 7.3.11 347 // ES6 19.1.3.2
348 BUILTIN(ObjectHasOwnProperty) { 348 RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty) {
Benedikt Meurer 2016/03/30 09:28:31 Please move this to runtime-something.cc
349 HandleScope scope(isolate); 349 HandleScope scope(isolate);
350 350 Handle<Object> property = args.at<Object>(1);
351 Handle<Object> property = args.atOrUndefined(isolate, 1);
352 351
353 Handle<Name> key; 352 Handle<Name> key;
354 uint32_t index; 353 uint32_t index;
355 bool key_is_array_index = property->ToArrayIndex(&index); 354 bool key_is_array_index = property->ToArrayIndex(&index);
356 355
357 if (!key_is_array_index) { 356 if (!key_is_array_index) {
358 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key, 357 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
359 Object::ToName(isolate, property)); 358 Object::ToName(isolate, property));
360 key_is_array_index = key->AsArrayIndex(&index); 359 key_is_array_index = key->AsArrayIndex(&index);
361 } 360 }
362 361
363 Handle<Object> object = args.receiver(); 362 Handle<Object> object = args.at<Object>(0);
364 363
365 if (object->IsJSObject()) { 364 if (object->IsJSObject()) {
366 Handle<JSObject> js_obj = Handle<JSObject>::cast(object); 365 Handle<JSObject> js_obj = Handle<JSObject>::cast(object);
367 // Fast case: either the key is a real named property or it is not 366 // Fast case: either the key is a real named property or it is not
368 // an array index and there are no interceptors or hidden 367 // an array index and there are no interceptors or hidden
369 // prototypes. 368 // prototypes.
370 // TODO(jkummerow): Make JSReceiver::HasOwnProperty fast enough to 369 // TODO(jkummerow): Make JSReceiver::HasOwnProperty fast enough to
371 // handle all cases directly (without this custom fast path). 370 // handle all cases directly (without this custom fast path).
372 { 371 {
373 LookupIterator::Configuration c = LookupIterator::OWN_SKIP_INTERCEPTOR; 372 LookupIterator::Configuration c = LookupIterator::OWN_SKIP_INTERCEPTOR;
(...skipping 41 matching lines...)
415 ? index < static_cast<uint32_t>(String::cast(*object)->length()) 414 ? index < static_cast<uint32_t>(String::cast(*object)->length())
416 : key->Equals(isolate->heap()->length_string())); 415 : key->Equals(isolate->heap()->length_string()));
417 } else if (object->IsNull() || object->IsUndefined()) { 416 } else if (object->IsNull() || object->IsUndefined()) {
418 THROW_NEW_ERROR_RETURN_FAILURE( 417 THROW_NEW_ERROR_RETURN_FAILURE(
419 isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject)); 418 isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject));
420 } 419 }
421 420
422 return isolate->heap()->false_value(); 421 return isolate->heap()->false_value();
423 } 422 }
424 423
424 void Builtins::Generate_ObjectHasOwnProperty(
425 compiler::CodeStubAssembler* assembler) {
426 typedef compiler::Node Node;
427 typedef compiler::CodeStubAssembler::Label Label;
428 typedef compiler::CodeStubAssembler::Variable Variable;
429
430 Node* object = assembler->Parameter(0);
431 Node* key = assembler->Parameter(1);
432 Node* context = assembler->Parameter(4);
433
434 Label call_runtime(assembler), return_true(assembler),
435 return_false(assembler);
436
437 // Smi receivers do not have own properties.
438 Label if_objectisnotsmi(assembler);
439 assembler->Branch(assembler->WordIsSmi(object), &return_false,
440 &if_objectisnotsmi);
441 assembler->Bind(&if_objectisnotsmi);
442
443 Node* map = assembler->LoadMap(object);
444 Node* instance_type = assembler->LoadMapInstanceType(map);
445
446 Variable var_index(assembler, MachineRepresentation::kWord32);
447
448 Label if_keyissmi(assembler), if_keyisnotsmi(assembler),
449 keyisindex(assembler);
450 assembler->Branch(assembler->WordIsSmi(key), &if_keyissmi, &if_keyisnotsmi);
451 assembler->Bind(&if_keyissmi);
452 {
453 // Negative smi keys are named properties. Handle in the runtime.
454 Label if_keyispositive(assembler);
455 assembler->Branch(assembler->WordIsPositiveSmi(key), &if_keyispositive,
456 &call_runtime);
457 assembler->Bind(&if_keyispositive);
458
459 var_index.Bind(assembler->SmiUntag(key));
460 assembler->Goto(&keyisindex);
461 }
462
463 assembler->Bind(&if_keyisnotsmi);
464
465 Node* key_instance_type = assembler->LoadInstanceType(key);
466 Label if_iskeyunique(assembler), if_iskeynotsymbol(assembler);
467 assembler->Branch(
468 assembler->Word32Equal(key_instance_type,
469 assembler->Int32Constant(SYMBOL_TYPE)),
470 &if_iskeyunique, &if_iskeynotsymbol);
471 assembler->Bind(&if_iskeynotsymbol);
472 {
473 Label if_iskeyinternalized(assembler);
474 Node* bits = assembler->WordAnd(
475 key_instance_type,
476 assembler->Int32Constant(kIsNotStringMask | kIsNotInternalizedMask));
477 assembler->Branch(
478 assembler->Word32Equal(
479 bits, assembler->Int32Constant(kStringTag | kInternalizedTag)),
480 &if_iskeyinternalized, &call_runtime);
481 assembler->Bind(&if_iskeyinternalized);
482
483 // Check whether the key is an array index passed in as string. Handle
484 // uniform with smi keys if so.
485 // TODO(verwaest): Also support non-internalized strings.
486 Node* hash = assembler->LoadNameHash(key);
487 Node* bit = assembler->Word32And(
488 hash, assembler->Int32Constant(internal::Name::kIsNotArrayIndexMask));
489 Label if_isarrayindex(assembler);
490 assembler->Branch(assembler->Word32Equal(bit, assembler->Int32Constant(0)),
491 &if_isarrayindex, &if_iskeyunique);
492 assembler->Bind(&if_isarrayindex);
493 var_index.Bind(
494 assembler->BitFieldDecode<internal::Name::ArrayIndexValueBits>(hash));
495 assembler->Goto(&keyisindex);
496 }
497 assembler->Bind(&if_iskeyunique);
498
499 {
500 Label if_objectissimple(assembler);
501 assembler->Branch(assembler->Int32LessThanOrEqual(
502 instance_type,
503 assembler->Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)),
504 &call_runtime, &if_objectissimple);
505 assembler->Bind(&if_objectissimple);
506 }
507
508 // TODO(verwaest): Perform a dictonary lookup on slow-mode receivers.
509 Node* bit_field3 = assembler->LoadMapBitField3(map);
510 Node* bit = assembler->BitFieldDecode<Map::DictionaryMap>(bit_field3);
511 Label if_isfastmap(assembler);
512 assembler->Branch(assembler->Word32Equal(bit, assembler->Int32Constant(0)),
513 &if_isfastmap, &call_runtime);
514 assembler->Bind(&if_isfastmap);
515 Node* nof =
516 assembler->BitFieldDecode<Map::NumberOfOwnDescriptorsBits>(bit_field3);
517 // Bail out to the runtime for large numbers of own descriptors. The stub only
518 // does linear search, which becomes too expensive in that case.
519 {
520 static const int32_t kMaxLinear = 256;
521 Label above_max(assembler), below_max(assembler);
522 assembler->Branch(assembler->Int32LessThanOrEqual(
523 nof, assembler->Int32Constant(kMaxLinear)),
524 &below_max, &call_runtime);
525 assembler->Bind(&below_max);
526 }
527 Node* descriptors = assembler->LoadMapDescriptors(map);
528
529 Variable var_descriptor(assembler, MachineRepresentation::kWord32);
530 Label loop(assembler, &var_descriptor);
531 var_descriptor.Bind(assembler->Int32Constant(0));
532 assembler->Goto(&loop);
533 assembler->Bind(&loop);
534 {
535 Node* index = var_descriptor.value();
536 Node* offset = assembler->Int32Constant(DescriptorArray::ToKeyIndex(0));
537 Node* factor = assembler->Int32Constant(DescriptorArray::kDescriptorSize);
538 Label if_notdone(assembler);
539 assembler->Branch(assembler->Word32Equal(index, nof), &return_false,
540 &if_notdone);
541 assembler->Bind(&if_notdone);
542 {
543 Node* array_index =
544 assembler->Int32Add(offset, assembler->Int32Mul(index, factor));
545 Node* current =
546 assembler->LoadFixedArrayElementInt32Index(descriptors, array_index);
547 Label if_unequal(assembler);
548 assembler->Branch(assembler->WordEqual(current, key), &return_true,
549 &if_unequal);
550 assembler->Bind(&if_unequal);
551
552 var_descriptor.Bind(
553 assembler->Int32Add(index, assembler->Int32Constant(1)));
554 assembler->Goto(&loop);
555 }
556 }
557
558 assembler->Bind(&keyisindex);
559 {
560 Label if_objectissimple(assembler);
561 assembler->Branch(assembler->Int32LessThanOrEqual(
562 instance_type, assembler->Int32Constant(
563 LAST_CUSTOM_ELEMENTS_RECEIVER)),
564 &call_runtime, &if_objectissimple);
565 assembler->Bind(&if_objectissimple);
566 }
567
568 Node* index = var_index.value();
569 Node* bit_field2 = assembler->LoadMapBitField2(map);
570 Node* elements_kind =
571 assembler->BitFieldDecode<Map::ElementsKindBits>(bit_field2);
572
573 // TODO(verwaest): Support other elements kinds as well.
574 Label if_isobjectorsmi(assembler);
575 assembler->Branch(
576 assembler->Int32LessThanOrEqual(
577 elements_kind, assembler->Int32Constant(FAST_HOLEY_ELEMENTS)),
578 &if_isobjectorsmi, &call_runtime);
579 assembler->Bind(&if_isobjectorsmi);
580 {
581 Node* elements = assembler->LoadElements(object);
582 Node* length = assembler->LoadFixedArrayBaseLength(elements);
583
584 Label if_iskeyinrange(assembler);
585 assembler->Branch(
586 assembler->Int32LessThan(index, assembler->SmiUntag(length)),
587 &if_iskeyinrange, &return_false);
588
589 assembler->Bind(&if_iskeyinrange);
590 Node* element = assembler->LoadFixedArrayElementInt32Index(elements, index);
591 Node* the_hole = assembler->LoadRoot(Heap::kTheHoleValueRootIndex);
592 assembler->Branch(assembler->WordEqual(element, the_hole), &return_false,
593 &return_true);
594 }
595
596 assembler->Bind(&return_true);
597 assembler->Return(assembler->BooleanConstant(true));
598
599 assembler->Bind(&return_false);
600 assembler->Return(assembler->BooleanConstant(false));
601
602 assembler->Bind(&call_runtime);
603 assembler->Return(assembler->CallRuntime(Runtime::kObjectHasOwnProperty,
604 context, object, key));
605 }
606
425 namespace { 607 namespace {
426 608
427 Object* DoArrayPush(Isolate* isolate, 609 Object* DoArrayPush(Isolate* isolate,
428 BuiltinArguments<BuiltinExtraArguments::kNone> args) { 610 BuiltinArguments<BuiltinExtraArguments::kNone> args) {
429 HandleScope scope(isolate); 611 HandleScope scope(isolate);
430 Handle<Object> receiver = args.receiver(); 612 Handle<Object> receiver = args.receiver();
431 if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1)) { 613 if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1)) {
432 return CallJsIntrinsic(isolate, isolate->array_push(), args); 614 return CallJsIntrinsic(isolate, isolate->array_push(), args);
433 } 615 }
434 // Fast Elements Path 616 // Fast Elements Path
(...skipping 4197 matching lines...)
4632 BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T) 4814 BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T)
4633 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) 4815 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
4634 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) 4816 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
4635 #undef DEFINE_BUILTIN_ACCESSOR_C 4817 #undef DEFINE_BUILTIN_ACCESSOR_C
4636 #undef DEFINE_BUILTIN_ACCESSOR_A 4818 #undef DEFINE_BUILTIN_ACCESSOR_A
4637 #undef DEFINE_BUILTIN_ACCESSOR_T 4819 #undef DEFINE_BUILTIN_ACCESSOR_T
4638 #undef DEFINE_BUILTIN_ACCESSOR_H 4820 #undef DEFINE_BUILTIN_ACCESSOR_H
4639 4821
4640 } // namespace internal 4822 } // namespace internal
4641 } // namespace v8 4823 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins.h ('k') | src/compiler/code-stub-assembler.h » ('j') | no next file with comments »

Powered by Google App Engine