OLD | NEW |
---|---|
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 6671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6682 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); | 6682 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); |
6683 DescriptorArray* new_descriptors; | 6683 DescriptorArray* new_descriptors; |
6684 MaybeObject* maybe_descriptors = | 6684 MaybeObject* maybe_descriptors = |
6685 descriptors->CopyUpTo(number_of_own_descriptors); | 6685 descriptors->CopyUpTo(number_of_own_descriptors); |
6686 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | 6686 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
6687 | 6687 |
6688 return CopyReplaceDescriptors(new_descriptors, OMIT_TRANSITION); | 6688 return CopyReplaceDescriptors(new_descriptors, OMIT_TRANSITION); |
6689 } | 6689 } |
6690 | 6690 |
6691 | 6691 |
6692 Handle<Map> Map::Copy(Handle<Map> map) { | |
6693 CALL_HEAP_FUNCTION(map->GetIsolate(), map->Copy(), Map); | |
6694 } | |
6695 | |
6696 | |
6692 MaybeObject* Map::Copy() { | 6697 MaybeObject* Map::Copy() { |
6693 DescriptorArray* descriptors = instance_descriptors(); | 6698 DescriptorArray* descriptors = instance_descriptors(); |
6694 DescriptorArray* new_descriptors; | 6699 DescriptorArray* new_descriptors; |
6695 int number_of_own_descriptors = NumberOfOwnDescriptors(); | 6700 int number_of_own_descriptors = NumberOfOwnDescriptors(); |
6696 MaybeObject* maybe_descriptors = | 6701 MaybeObject* maybe_descriptors = |
6697 descriptors->CopyUpTo(number_of_own_descriptors); | 6702 descriptors->CopyUpTo(number_of_own_descriptors); |
6698 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | 6703 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
6699 | 6704 |
6700 return CopyReplaceDescriptors(new_descriptors, OMIT_TRANSITION); | 6705 return CopyReplaceDescriptors(new_descriptors, OMIT_TRANSITION); |
6701 } | 6706 } |
(...skipping 2691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
9393 if (!shared_info->script()->IsScript()) return false; | 9398 if (!shared_info->script()->IsScript()) return false; |
9394 if (shared_info->optimization_disabled()) return false; | 9399 if (shared_info->optimization_disabled()) return false; |
9395 Code* code = shared_info->code(); | 9400 Code* code = shared_info->code(); |
9396 if (code->kind() == Code::OPTIMIZED_FUNCTION) return true; | 9401 if (code->kind() == Code::OPTIMIZED_FUNCTION) return true; |
9397 // If we never ran this (unlikely) then lets try to optimize it. | 9402 // If we never ran this (unlikely) then lets try to optimize it. |
9398 if (code->kind() != Code::FUNCTION) return true; | 9403 if (code->kind() != Code::FUNCTION) return true; |
9399 return code->optimizable(); | 9404 return code->optimizable(); |
9400 } | 9405 } |
9401 | 9406 |
9402 | 9407 |
9408 void JSObject::OptimizeAsPrototype(Handle<JSObject> object) { | |
9409 CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), object->OptimizeAsPrototype()); | |
9410 } | |
9411 | |
9412 | |
9403 MaybeObject* JSObject::OptimizeAsPrototype() { | 9413 MaybeObject* JSObject::OptimizeAsPrototype() { |
9404 if (IsGlobalObject()) return this; | 9414 if (IsGlobalObject()) return this; |
9405 | 9415 |
9406 // Make sure prototypes are fast objects and their maps have the bit set | 9416 // Make sure prototypes are fast objects and their maps have the bit set |
9407 // so they remain fast. | 9417 // so they remain fast. |
9408 if (!HasFastProperties()) { | 9418 if (!HasFastProperties()) { |
9409 MaybeObject* new_proto = TransformToFastProperties(0); | 9419 MaybeObject* new_proto = TransformToFastProperties(0); |
9410 if (new_proto->IsFailure()) return new_proto; | 9420 if (new_proto->IsFailure()) return new_proto; |
9411 ASSERT(new_proto == this); | 9421 ASSERT(new_proto == this); |
9412 } | 9422 } |
(...skipping 1592 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
11005 isolate->factory()->NewNumberFromUint(delete_count), | 11015 isolate->factory()->NewNumberFromUint(delete_count), |
11006 NONE, kNonStrictMode); | 11016 NONE, kNonStrictMode); |
11007 } | 11017 } |
11008 | 11018 |
11009 EnqueueSpliceRecord(self, index, deleted, add_count); | 11019 EnqueueSpliceRecord(self, index, deleted, add_count); |
11010 | 11020 |
11011 return *hresult; | 11021 return *hresult; |
11012 } | 11022 } |
11013 | 11023 |
11014 | 11024 |
11015 Map* Map::GetPrototypeTransition(Object* prototype) { | 11025 Handle<Map> Map::GetPrototypeTransition(Handle<Map> map, |
11016 FixedArray* cache = GetPrototypeTransitions(); | 11026 Handle<Object> prototype) { |
11017 int number_of_transitions = NumberOfProtoTransitions(); | 11027 FixedArray* cache = map->GetPrototypeTransitions(); |
11028 int number_of_transitions = map->NumberOfProtoTransitions(); | |
11018 const int proto_offset = | 11029 const int proto_offset = |
11019 kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset; | 11030 kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset; |
11020 const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset; | 11031 const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset; |
11021 const int step = kProtoTransitionElementsPerEntry; | 11032 const int step = kProtoTransitionElementsPerEntry; |
11022 for (int i = 0; i < number_of_transitions; i++) { | 11033 for (int i = 0; i < number_of_transitions; i++) { |
11023 if (cache->get(proto_offset + i * step) == prototype) { | 11034 if (cache->get(proto_offset + i * step) == *prototype) { |
11024 Object* map = cache->get(map_offset + i * step); | 11035 Object* result = cache->get(map_offset + i * step); |
11025 return Map::cast(map); | 11036 return Handle<Map>(Map::cast(result)); |
rossberg
2013/07/02 12:08:01
Don't forget to pass the isolate.
Michael Starzinger
2013/07/02 15:20:15
As dicussed offline, it's not needed to pass the i
| |
11026 } | 11037 } |
11027 } | 11038 } |
11028 return NULL; | 11039 return Handle<Map>(); |
11029 } | 11040 } |
11030 | 11041 |
11031 | 11042 |
11032 MaybeObject* Map::PutPrototypeTransition(Object* prototype, Map* map) { | 11043 Handle<Map> Map::PutPrototypeTransition(Handle<Map> map, |
11033 ASSERT(map->IsMap()); | 11044 Handle<Object> prototype, |
11034 ASSERT(HeapObject::cast(prototype)->map()->IsMap()); | 11045 Handle<Map> target_map) { |
11046 ASSERT(target_map->IsMap()); | |
11047 ASSERT(HeapObject::cast(*prototype)->map()->IsMap()); | |
11035 // Don't cache prototype transition if this map is shared. | 11048 // Don't cache prototype transition if this map is shared. |
11036 if (is_shared() || !FLAG_cache_prototype_transitions) return this; | 11049 if (map->is_shared() || !FLAG_cache_prototype_transitions) return map; |
11037 | |
11038 FixedArray* cache = GetPrototypeTransitions(); | |
11039 | 11050 |
11040 const int step = kProtoTransitionElementsPerEntry; | 11051 const int step = kProtoTransitionElementsPerEntry; |
11041 const int header = kProtoTransitionHeaderSize; | 11052 const int header = kProtoTransitionHeaderSize; |
11042 | 11053 |
11054 Handle<FixedArray> cache(map->GetPrototypeTransitions()); | |
rossberg
2013/07/02 12:08:01
Pass the isolate.
Michael Starzinger
2013/07/02 15:20:15
Likeiwse.
| |
11043 int capacity = (cache->length() - header) / step; | 11055 int capacity = (cache->length() - header) / step; |
11044 | 11056 int transitions = map->NumberOfProtoTransitions() + 1; |
11045 int transitions = NumberOfProtoTransitions() + 1; | |
11046 | 11057 |
11047 if (transitions > capacity) { | 11058 if (transitions > capacity) { |
11048 if (capacity > kMaxCachedPrototypeTransitions) return this; | 11059 if (capacity > kMaxCachedPrototypeTransitions) return map; |
11049 | 11060 |
11050 FixedArray* new_cache; | |
11051 // Grow array by factor 2 over and above what we need. | 11061 // Grow array by factor 2 over and above what we need. |
11052 { MaybeObject* maybe_cache = | 11062 Factory* factory = map->GetIsolate()->factory(); |
11053 GetHeap()->AllocateFixedArray(transitions * 2 * step + header); | 11063 cache = factory->CopySizeFixedArray(cache, transitions * 2 * step + header); |
11054 if (!maybe_cache->To(&new_cache)) return maybe_cache; | |
11055 } | |
11056 | 11064 |
11057 for (int i = 0; i < capacity * step; i++) { | 11065 CALL_AND_RETRY_OR_DIE(map->GetIsolate(), |
11058 new_cache->set(i + header, cache->get(i + header)); | 11066 map->SetPrototypeTransitions(*cache), |
11059 } | 11067 break, |
11060 cache = new_cache; | 11068 return Handle<Map>()); |
11061 MaybeObject* set_result = SetPrototypeTransitions(cache); | |
11062 if (set_result->IsFailure()) return set_result; | |
11063 } | 11069 } |
11064 | 11070 |
11065 int last = transitions - 1; | 11071 // Reload number of transitions as GC might shrink them. |
11072 int last = map->NumberOfProtoTransitions(); | |
11073 int entry = header + last * step; | |
11066 | 11074 |
11067 cache->set(header + last * step + kProtoTransitionPrototypeOffset, prototype); | 11075 cache->set(entry + kProtoTransitionPrototypeOffset, *prototype); |
11068 cache->set(header + last * step + kProtoTransitionMapOffset, map); | 11076 cache->set(entry + kProtoTransitionMapOffset, *target_map); |
11069 SetNumberOfProtoTransitions(transitions); | 11077 map->SetNumberOfProtoTransitions(transitions); |
11070 | 11078 |
11071 return cache; | 11079 return map; |
11072 } | 11080 } |
11073 | 11081 |
11074 | 11082 |
11075 void Map::ZapTransitions() { | 11083 void Map::ZapTransitions() { |
11076 TransitionArray* transition_array = transitions(); | 11084 TransitionArray* transition_array = transitions(); |
11077 // TODO(mstarzinger): Temporarily use a slower version instead of the faster | 11085 // TODO(mstarzinger): Temporarily use a slower version instead of the faster |
11078 // MemsetPointer to investigate a crasher. Switch back to MemsetPointer. | 11086 // MemsetPointer to investigate a crasher. Switch back to MemsetPointer. |
11079 Object** data = transition_array->data_start(); | 11087 Object** data = transition_array->data_start(); |
11080 Object* the_hole = GetHeap()->the_hole_value(); | 11088 Object* the_hole = GetHeap()->the_hole_value(); |
11081 int length = transition_array->length(); | 11089 int length = transition_array->length(); |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
11284 int removed = end - start; | 11292 int removed = end - start; |
11285 for (int i = code_entries - removed; i < code_entries; i++) { | 11293 for (int i = code_entries - removed; i < code_entries; i++) { |
11286 clear_at(i); | 11294 clear_at(i); |
11287 } | 11295 } |
11288 set_number_of_entries(group, 0); | 11296 set_number_of_entries(group, 0); |
11289 DeoptimizeDependentCodeFilter filter; | 11297 DeoptimizeDependentCodeFilter filter; |
11290 Deoptimizer::DeoptimizeAllFunctionsWith(isolate, &filter); | 11298 Deoptimizer::DeoptimizeAllFunctionsWith(isolate, &filter); |
11291 } | 11299 } |
11292 | 11300 |
11293 | 11301 |
11294 MaybeObject* JSReceiver::SetPrototype(Object* value, | 11302 Handle<Object> JSObject::SetPrototype(Handle<JSObject> object, |
11303 Handle<Object> value, | |
11295 bool skip_hidden_prototypes) { | 11304 bool skip_hidden_prototypes) { |
11296 #ifdef DEBUG | 11305 #ifdef DEBUG |
11297 int size = Size(); | 11306 int size = object->Size(); |
11298 #endif | 11307 #endif |
11299 | 11308 |
11300 Isolate* isolate = GetIsolate(); | 11309 Isolate* isolate = object->GetIsolate(); |
11301 Heap* heap = isolate->heap(); | 11310 Heap* heap = isolate->heap(); |
11302 // Silently ignore the change if value is not a JSObject or null. | 11311 // Silently ignore the change if value is not a JSObject or null. |
11303 // SpiderMonkey behaves this way. | 11312 // SpiderMonkey behaves this way. |
11304 if (!value->IsJSReceiver() && !value->IsNull()) return value; | 11313 if (!value->IsJSReceiver() && !value->IsNull()) return value; |
11305 | 11314 |
11306 // From 8.6.2 Object Internal Methods | 11315 // From 8.6.2 Object Internal Methods |
11307 // ... | 11316 // ... |
11308 // In addition, if [[Extensible]] is false the value of the [[Class]] and | 11317 // In addition, if [[Extensible]] is false the value of the [[Class]] and |
11309 // [[Prototype]] internal properties of the object may not be modified. | 11318 // [[Prototype]] internal properties of the object may not be modified. |
11310 // ... | 11319 // ... |
11311 // Implementation specific extensions that modify [[Class]], [[Prototype]] | 11320 // Implementation specific extensions that modify [[Class]], [[Prototype]] |
11312 // or [[Extensible]] must not violate the invariants defined in the preceding | 11321 // or [[Extensible]] must not violate the invariants defined in the preceding |
11313 // paragraph. | 11322 // paragraph. |
11314 if (!this->map()->is_extensible()) { | 11323 if (!object->map()->is_extensible()) { |
11315 HandleScope scope(isolate); | 11324 Handle<Object> args[] = { object }; |
11316 Handle<Object> handle(this, isolate); | 11325 Handle<Object> error = isolate->factory()->NewTypeError( |
11317 return isolate->Throw( | 11326 "non_extensible_proto", HandleVector(args, ARRAY_SIZE(args))); |
11318 *isolate->factory()->NewTypeError("non_extensible_proto", | 11327 isolate->Throw(*error); |
11319 HandleVector<Object>(&handle, 1))); | 11328 return Handle<Object>(); |
11320 } | 11329 } |
11321 | 11330 |
11322 // Before we can set the prototype we need to be sure | 11331 // Before we can set the prototype we need to be sure |
11323 // prototype cycles are prevented. | 11332 // prototype cycles are prevented. |
11324 // It is sufficient to validate that the receiver is not in the new prototype | 11333 // It is sufficient to validate that the receiver is not in the new prototype |
11325 // chain. | 11334 // chain. |
11326 for (Object* pt = value; | 11335 for (Object* pt = *value; |
11327 pt != heap->null_value(); | 11336 pt != heap->null_value(); |
11328 pt = pt->GetPrototype(isolate)) { | 11337 pt = pt->GetPrototype(isolate)) { |
11329 if (JSReceiver::cast(pt) == this) { | 11338 if (JSReceiver::cast(pt) == *object) { |
11330 // Cycle detected. | 11339 // Cycle detected. |
11331 HandleScope scope(isolate); | 11340 Handle<Object> error = isolate->factory()->NewError( |
11332 return isolate->Throw( | 11341 "cyclic_proto", HandleVector<Object>(NULL, 0)); |
11333 *isolate->factory()->NewError("cyclic_proto", | 11342 isolate->Throw(*error); |
11334 HandleVector<Object>(NULL, 0))); | 11343 return Handle<Object>(); |
11335 } | 11344 } |
11336 } | 11345 } |
11337 | 11346 |
11338 JSReceiver* real_receiver = this; | 11347 Handle<JSObject> real_receiver = object; |
11339 | 11348 |
11340 if (skip_hidden_prototypes) { | 11349 if (skip_hidden_prototypes) { |
11341 // Find the first object in the chain whose prototype object is not | 11350 // Find the first object in the chain whose prototype object is not |
11342 // hidden and set the new prototype on that object. | 11351 // hidden and set the new prototype on that object. |
11343 Object* current_proto = real_receiver->GetPrototype(); | 11352 Object* current_proto = real_receiver->GetPrototype(); |
11344 while (current_proto->IsJSObject() && | 11353 while (current_proto->IsJSObject() && |
11345 JSReceiver::cast(current_proto)->map()->is_hidden_prototype()) { | 11354 JSObject::cast(current_proto)->map()->is_hidden_prototype()) { |
11346 real_receiver = JSReceiver::cast(current_proto); | 11355 real_receiver = Handle<JSObject>(JSObject::cast(current_proto)); |
rossberg
2013/07/02 12:08:01
Pass the isolate. Also, you can use handle(..., is
Michael Starzinger
2013/07/02 15:20:15
Done, switched to handle(..., isolate) to avoid ty
| |
11347 current_proto = current_proto->GetPrototype(isolate); | 11356 current_proto = current_proto->GetPrototype(isolate); |
11348 } | 11357 } |
11349 } | 11358 } |
11350 | 11359 |
11351 // Set the new prototype of the object. | 11360 // Set the new prototype of the object. |
11352 Map* map = real_receiver->map(); | 11361 Handle<Map> map(real_receiver->map()); |
rossberg
2013/07/02 12:08:01
Pass the isolate.
Michael Starzinger
2013/07/02 15:20:15
Likewise.
| |
11353 | 11362 |
11354 // Nothing to do if prototype is already set. | 11363 // Nothing to do if prototype is already set. |
11355 if (map->prototype() == value) return value; | 11364 if (map->prototype() == *value) return value; |
11356 | 11365 |
11357 if (value->IsJSObject()) { | 11366 if (value->IsJSObject()) { |
11358 MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype(); | 11367 JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value)); |
11359 if (ok->IsFailure()) return ok; | |
11360 } | 11368 } |
11361 | 11369 |
11362 Map* new_map = map->GetPrototypeTransition(value); | 11370 Handle<Map> new_map = Map::GetPrototypeTransition(map, value); |
11363 if (new_map == NULL) { | 11371 if (new_map.is_null()) { |
11364 MaybeObject* maybe_new_map = map->Copy(); | 11372 new_map = Map::Copy(map); |
11365 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 11373 Map::PutPrototypeTransition(map, value, new_map); |
11366 | 11374 new_map->set_prototype(*value); |
11367 MaybeObject* maybe_new_cache = | |
11368 map->PutPrototypeTransition(value, new_map); | |
11369 if (maybe_new_cache->IsFailure()) return maybe_new_cache; | |
11370 | |
11371 new_map->set_prototype(value); | |
11372 } | 11375 } |
11373 ASSERT(new_map->prototype() == value); | 11376 ASSERT(new_map->prototype() == *value); |
11374 real_receiver->set_map(new_map); | 11377 real_receiver->set_map(*new_map); |
11375 | 11378 |
11376 heap->ClearInstanceofCache(); | 11379 heap->ClearInstanceofCache(); |
11377 ASSERT(size == Size()); | 11380 ASSERT(size == object->Size()); |
11378 return value; | 11381 return value; |
11379 } | 11382 } |
11380 | 11383 |
11381 | 11384 |
11382 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args, | 11385 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args, |
11383 uint32_t first_arg, | 11386 uint32_t first_arg, |
11384 uint32_t arg_count, | 11387 uint32_t arg_count, |
11385 EnsureElementsMode mode) { | 11388 EnsureElementsMode mode) { |
11386 // Elements in |Arguments| are ordered backwards (because they're on the | 11389 // Elements in |Arguments| are ordered backwards (because they're on the |
11387 // stack), but the method that's called here iterates over them in forward | 11390 // stack), but the method that's called here iterates over them in forward |
(...skipping 4431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
15819 | 15822 |
15820 void PropertyCell::AddDependentCode(Handle<Code> code) { | 15823 void PropertyCell::AddDependentCode(Handle<Code> code) { |
15821 Handle<DependentCode> codes = DependentCode::Insert( | 15824 Handle<DependentCode> codes = DependentCode::Insert( |
15822 Handle<DependentCode>(dependent_code()), | 15825 Handle<DependentCode>(dependent_code()), |
15823 DependentCode::kPropertyCellChangedGroup, code); | 15826 DependentCode::kPropertyCellChangedGroup, code); |
15824 if (*codes != dependent_code()) set_dependent_code(*codes); | 15827 if (*codes != dependent_code()) set_dependent_code(*codes); |
15825 } | 15828 } |
15826 | 15829 |
15827 | 15830 |
15828 } } // namespace v8::internal | 15831 } } // namespace v8::internal |
OLD | NEW |