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

Side by Side Diff: src/isolate.cc

Issue 1409123003: [runtime] Avoid @@isConcatSpreadable lookup for fast path Array.prototype.concat (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: simplifications Created 5 years, 1 month 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/isolate.h" 5 #include "src/isolate.h"
6 6
7 #include <stdlib.h> 7 #include <stdlib.h>
8 8
9 #include <fstream> // NOLINT(readability/streams) 9 #include <fstream> // NOLINT(readability/streams)
10 #include <sstream> 10 #include <sstream>
(...skipping 2415 matching lines...) Expand 10 before | Expand all | Expand 10 after
2426 } 2426 }
2427 2427
2428 2428
2429 bool Isolate::use_crankshaft() const { 2429 bool Isolate::use_crankshaft() const {
2430 return FLAG_crankshaft && 2430 return FLAG_crankshaft &&
2431 !serializer_enabled_ && 2431 !serializer_enabled_ &&
2432 CpuFeatures::SupportsCrankshaft(); 2432 CpuFeatures::SupportsCrankshaft();
2433 } 2433 }
2434 2434
2435 2435
2436 Context* Isolate::ContextForArrayOrObjectPrototype(Handle<JSObject> object) {
2437 Object* context = heap()->native_contexts_list();
2438 while (!context->IsUndefined()) {
2439 Context* current_context = Context::cast(context);
2440 if (current_context->initial_object_prototype() == *object ||
2441 current_context->initial_array_prototype() == *object) {
2442 return current_context;
2443 }
2444 context = current_context->get(Context::NEXT_CONTEXT_LINK);
2445 }
2446 return NULL;
2447 }
2448
2449
2450 bool Isolate::IsArrayIsConcatSpreadableSet() {
2451 PropertyCell* is_concat_spreadable_cell =
2452 heap()->array_is_concat_spreadable_protector();
2453 bool is_concat_spreadable_set =
2454 is_concat_spreadable_cell->value()->IsSmi() &&
2455 Smi::cast(is_concat_spreadable_cell->value())->value() ==
2456 kArrayIsConcatSpreadableProtectorInvalid;
2457
2458 #ifdef DEBUG
2459 Map* root_array_map = get_initial_js_array_map(GetInitialFastElementsKind());
2460 if (root_array_map == NULL) {
2461 //
2462 return is_concat_spreadable_set;
2463 }
2464
2465 Handle<Object> array_prototype(array_function()->prototype(), this);
2466 Handle<Symbol> key(factory()->is_concat_spreadable_symbol());
2467 Handle<Object> value;
2468 MaybeHandle<Object> maybeValue =
2469 i::Runtime::GetObjectProperty(this, array_prototype, key);
2470 if (maybeValue.ToHandle(&value) && !value->IsUndefined()) {
Toon Verwaest 2015/11/02 12:32:45 Plus o[@@isConcatSpreadable] = undefined
Camillo Bruni 2015/11/03 14:49:25 ?
2471 // TODO(cbruni): Currently we do not revert if we unset the
2472 // isConcatSpreadable property on Array.prototype or Object.prototype hence
2473 // the reverse implication doesn't hold.
2474 DCHECK(is_concat_spreadable_set);
2475 return true;
2476 }
2477 #endif // DEBUG
2478
2479 return is_concat_spreadable_set;
2480 }
2481
2482
2483 void Isolate::UpdateArrayIsConcatSpreadableProtectorOnAddProperty(
2484 Handle<JSObject> object, Handle<Name> name) {
2485 // The invalidate the is_concat_spreadable_protector invalidation is a one-way
2486 // action.
2487 if (IsArrayIsConcatSpreadableSet()) return;
2488 if (!object->map()->is_prototype_map()) return;
2489 Handle<Name> key(factory()->is_concat_spreadable_symbol());
Toon Verwaest 2015/11/02 12:32:45 key = factory()->is_concat_spreadable_symbol();
Camillo Bruni 2015/11/03 14:49:25 right
2490 if (!Name::Equals(name, key)) return;
2491 Context* context = ContextForArrayOrObjectPrototype(object);
2492 if (context == NULL) return;
2493 PropertyCell::SetValueWithInvalidation(
2494 factory()->array_is_concat_spreadable_protector(),
2495 handle(Smi::FromInt(kArrayElementsProtectorInvalid), this));
2496 }
2497
2498
2436 bool Isolate::IsFastArrayConstructorPrototypeChainIntact() { 2499 bool Isolate::IsFastArrayConstructorPrototypeChainIntact() {
2437 PropertyCell* no_elements_cell = heap()->array_protector(); 2500 PropertyCell* no_elements_cell = heap()->array_elements_protector();
2438 bool cell_reports_intact = 2501 bool cell_reports_intact = no_elements_cell->value()->IsSmi() &&
2439 no_elements_cell->value()->IsSmi() && 2502 Smi::cast(no_elements_cell->value())->value() ==
2440 Smi::cast(no_elements_cell->value())->value() == kArrayProtectorValid; 2503 kArrayElementsProtectorValid;
2441 2504
2442 #ifdef DEBUG 2505 #ifdef DEBUG
2443 Map* root_array_map = 2506 Map* root_array_map =
2444 get_initial_js_array_map(GetInitialFastElementsKind()); 2507 get_initial_js_array_map(GetInitialFastElementsKind());
2445 Context* native_context = context()->native_context(); 2508 Context* native_context = context()->native_context();
2446 JSObject* initial_array_proto = JSObject::cast( 2509 JSObject* initial_array_proto =
2447 native_context->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX)); 2510 JSObject::cast(native_context->initial_array_prototype());
2448 JSObject* initial_object_proto = JSObject::cast( 2511 JSObject* initial_object_proto =
2449 native_context->get(Context::INITIAL_OBJECT_PROTOTYPE_INDEX)); 2512 JSObject::cast(native_context->initial_object_prototype());
2450 2513
2451 if (root_array_map == NULL || initial_array_proto == initial_object_proto) { 2514 if (root_array_map == NULL || initial_array_proto == initial_object_proto) {
2452 // We are in the bootstrapping process, and the entire check sequence 2515 // We are in the bootstrapping process, and the entire check sequence
2453 // shouldn't be performed. 2516 // shouldn't be performed.
2454 return cell_reports_intact; 2517 return cell_reports_intact;
2455 } 2518 }
2456 2519
2457 // Check that the array prototype hasn't been altered WRT empty elements. 2520 // Check that the array prototype hasn't been altered WRT empty elements.
2458 if (root_array_map->prototype() != initial_array_proto) { 2521 if (root_array_map->prototype() != initial_array_proto) {
2459 DCHECK_EQ(false, cell_reports_intact); 2522 DCHECK_EQ(false, cell_reports_intact);
2460 return cell_reports_intact; 2523 return false;
2461 } 2524 }
2462 2525
2463 FixedArrayBase* elements = initial_array_proto->elements(); 2526 FixedArrayBase* elements = initial_array_proto->elements();
2464 if (elements != heap()->empty_fixed_array() && 2527 if (elements != heap()->empty_fixed_array() &&
2465 elements != heap()->empty_slow_element_dictionary()) { 2528 elements != heap()->empty_slow_element_dictionary()) {
2466 DCHECK_EQ(false, cell_reports_intact); 2529 DCHECK_EQ(false, cell_reports_intact);
2467 return cell_reports_intact; 2530 return false;
2468 } 2531 }
2469 2532
2470 // Check that the object prototype hasn't been altered WRT empty elements. 2533 // Check that the object prototype hasn't been altered WRT empty elements.
2471 PrototypeIterator iter(this, initial_array_proto); 2534 PrototypeIterator iter(this, initial_array_proto);
2472 if (iter.IsAtEnd() || iter.GetCurrent() != initial_object_proto) { 2535 if (iter.IsAtEnd() || iter.GetCurrent() != initial_object_proto) {
2473 DCHECK_EQ(false, cell_reports_intact); 2536 DCHECK_EQ(false, cell_reports_intact);
2474 return cell_reports_intact; 2537 return false;
2475 } 2538 }
2476 2539
2477 elements = initial_object_proto->elements(); 2540 elements = initial_object_proto->elements();
2478 if (elements != heap()->empty_fixed_array() && 2541 if (elements != heap()->empty_fixed_array() &&
2479 elements != heap()->empty_slow_element_dictionary()) { 2542 elements != heap()->empty_slow_element_dictionary()) {
2480 DCHECK_EQ(false, cell_reports_intact); 2543 DCHECK_EQ(false, cell_reports_intact);
2481 return cell_reports_intact; 2544 return false;
2482 } 2545 }
2483 2546
2484 iter.Advance(); 2547 iter.Advance();
2485 if (!iter.IsAtEnd()) { 2548 if (!iter.IsAtEnd()) {
2486 DCHECK_EQ(false, cell_reports_intact); 2549 DCHECK_EQ(false, cell_reports_intact);
2487 return cell_reports_intact; 2550 return false;
2488 } 2551 }
2489 2552
2490 #endif 2553 #endif
2491 2554
2492 return cell_reports_intact; 2555 return cell_reports_intact;
2493 } 2556 }
2494 2557
2495 2558
2496 void Isolate::UpdateArrayProtectorOnSetElement(Handle<JSObject> object) { 2559 void Isolate::UpdateArrayProtectorOnSetElement(Handle<JSObject> object) {
2497 if (IsFastArrayConstructorPrototypeChainIntact() && 2560 if (!IsFastArrayConstructorPrototypeChainIntact()) return;
2498 object->map()->is_prototype_map()) { 2561 if (!object->map()->is_prototype_map()) return;
2499 Object* context = heap()->native_contexts_list(); 2562 Context* context = ContextForArrayOrObjectPrototype(object);
2500 while (!context->IsUndefined()) { 2563 if (context == NULL) return;
2501 Context* current_context = Context::cast(context); 2564 PropertyCell::SetValueWithInvalidation(
2502 if (current_context->get(Context::INITIAL_OBJECT_PROTOTYPE_INDEX) == 2565 factory()->array_elements_protector(),
2503 *object || 2566 handle(Smi::FromInt(kArrayElementsProtectorInvalid), this));
2504 current_context->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX) ==
2505 *object) {
2506 PropertyCell::SetValueWithInvalidation(
2507 factory()->array_protector(),
2508 handle(Smi::FromInt(kArrayProtectorInvalid), this));
2509 break;
2510 }
2511 context = current_context->get(Context::NEXT_CONTEXT_LINK);
2512 }
2513 }
2514 } 2567 }
2515 2568
2516 2569
2517 bool Isolate::IsAnyInitialArrayPrototype(Handle<JSArray> array) { 2570 bool Isolate::IsAnyInitialArrayPrototype(Handle<JSArray> array) {
2518 if (array->map()->is_prototype_map()) { 2571 if (!array->map()->is_prototype_map()) return false;
2519 Object* context = heap()->native_contexts_list(); 2572 Object* context = heap()->native_contexts_list();
2520 while (!context->IsUndefined()) { 2573 while (!context->IsUndefined()) {
2521 Context* current_context = Context::cast(context); 2574 Context* current_context = Context::cast(context);
2522 if (current_context->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX) == 2575 if (current_context->initial_array_prototype() == *array) {
2523 *array) { 2576 return true;
2524 return true;
2525 }
2526 context = current_context->get(Context::NEXT_CONTEXT_LINK);
2527 } 2577 }
2578 context = current_context->get(Context::NEXT_CONTEXT_LINK);
2528 } 2579 }
2529 return false; 2580 return false;
2530 } 2581 }
2531 2582
2532 2583
2533 CallInterfaceDescriptorData* Isolate::call_descriptor_data(int index) { 2584 CallInterfaceDescriptorData* Isolate::call_descriptor_data(int index) {
2534 DCHECK(0 <= index && index < CallDescriptors::NUMBER_OF_DESCRIPTORS); 2585 DCHECK(0 <= index && index < CallDescriptors::NUMBER_OF_DESCRIPTORS);
2535 return &call_descriptor_data_[index]; 2586 return &call_descriptor_data_[index];
2536 } 2587 }
2537 2588
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after
2849 // Then check whether this scope intercepts. 2900 // Then check whether this scope intercepts.
2850 if ((flag & intercept_mask_)) { 2901 if ((flag & intercept_mask_)) {
2851 intercepted_flags_ |= flag; 2902 intercepted_flags_ |= flag;
2852 return true; 2903 return true;
2853 } 2904 }
2854 return false; 2905 return false;
2855 } 2906 }
2856 2907
2857 } // namespace internal 2908 } // namespace internal
2858 } // namespace v8 2909 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698