OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |