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

Side by Side Diff: src/objects.cc

Issue 18089024: Handlify JSObject::SetPrototype method. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 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 | Annotate | Revision Log
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.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 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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698