OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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/objects.h" | 5 #include "src/objects.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 #include <iomanip> | 8 #include <iomanip> |
9 #include <sstream> | 9 #include <sstream> |
10 | 10 |
(...skipping 12188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12199 } | 12199 } |
12200 | 12200 |
12201 } // namespace | 12201 } // namespace |
12202 #endif | 12202 #endif |
12203 | 12203 |
12204 | 12204 |
12205 void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) { | 12205 void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) { |
12206 if (function->has_initial_map()) return; | 12206 if (function->has_initial_map()) return; |
12207 Isolate* isolate = function->GetIsolate(); | 12207 Isolate* isolate = function->GetIsolate(); |
12208 | 12208 |
| 12209 // The constructor should be compiled for the optimization hints to be |
| 12210 // available. |
| 12211 Compiler::Compile(function, CLEAR_EXCEPTION); |
| 12212 |
12209 // First create a new map with the size and number of in-object properties | 12213 // First create a new map with the size and number of in-object properties |
12210 // suggested by the function. | 12214 // suggested by the function. |
12211 InstanceType instance_type; | 12215 InstanceType instance_type; |
12212 if (function->shared()->is_generator()) { | 12216 if (function->shared()->is_generator()) { |
12213 instance_type = JS_GENERATOR_OBJECT_TYPE; | 12217 instance_type = JS_GENERATOR_OBJECT_TYPE; |
12214 } else { | 12218 } else { |
12215 instance_type = JS_OBJECT_TYPE; | 12219 instance_type = JS_OBJECT_TYPE; |
12216 } | 12220 } |
12217 int instance_size; | 12221 int instance_size; |
12218 int in_object_properties; | 12222 int in_object_properties; |
(...skipping 19 matching lines...) Expand all Loading... |
12238 // Finally link initial map and constructor function. | 12242 // Finally link initial map and constructor function. |
12239 DCHECK(prototype->IsJSReceiver()); | 12243 DCHECK(prototype->IsJSReceiver()); |
12240 JSFunction::SetInitialMap(function, map, prototype); | 12244 JSFunction::SetInitialMap(function, map, prototype); |
12241 | 12245 |
12242 if (!function->shared()->is_generator()) { | 12246 if (!function->shared()->is_generator()) { |
12243 function->StartInobjectSlackTracking(); | 12247 function->StartInobjectSlackTracking(); |
12244 } | 12248 } |
12245 } | 12249 } |
12246 | 12250 |
12247 | 12251 |
12248 Handle<Map> JSFunction::EnsureDerivedHasInitialMap( | 12252 // static |
12249 Handle<JSFunction> new_target, Handle<JSFunction> constructor) { | 12253 MaybeHandle<Map> JSFunction::GetDerivedMap(Isolate* isolate, |
12250 DCHECK(constructor->has_initial_map()); | 12254 Handle<JSFunction> constructor, |
12251 Isolate* isolate = constructor->GetIsolate(); | 12255 Handle<JSReceiver> new_target) { |
| 12256 EnsureHasInitialMap(constructor); |
| 12257 |
12252 Handle<Map> constructor_initial_map(constructor->initial_map(), isolate); | 12258 Handle<Map> constructor_initial_map(constructor->initial_map(), isolate); |
12253 if (*new_target == *constructor) return constructor_initial_map; | 12259 if (*new_target == *constructor) return constructor_initial_map; |
12254 if (new_target->has_initial_map()) { | 12260 |
12255 // Check that |new_target|'s initial map still in sync with | 12261 if (new_target->IsJSProxy()) { |
12256 // the |constructor|, otherwise we must create a new initial map for | 12262 Handle<JSProxy> new_target_proxy = Handle<JSProxy>::cast(new_target); |
12257 // |new_target|. | 12263 Handle<Object> prototype; |
12258 if (new_target->initial_map()->GetConstructor() == *constructor) { | 12264 Handle<String> prototype_string = isolate->factory()->prototype_string(); |
12259 return handle(new_target->initial_map(), isolate); | 12265 ASSIGN_RETURN_ON_EXCEPTION( |
| 12266 isolate, prototype, |
| 12267 JSReceiver::GetProperty(new_target_proxy, prototype_string), Map); |
| 12268 Handle<Map> map = Map::CopyInitialMap(constructor_initial_map); |
| 12269 |
| 12270 if (!prototype->IsJSReceiver()) { |
| 12271 Handle<Context> context; |
| 12272 ASSIGN_RETURN_ON_EXCEPTION( |
| 12273 isolate, context, JSProxy::GetFunctionRealm(new_target_proxy), Map); |
| 12274 DCHECK(context->IsNativeContext()); |
| 12275 // TODO(verwaest): Use the intrinsicDefaultProto instead. |
| 12276 prototype = handle(context->initial_object_prototype(), isolate); |
12260 } | 12277 } |
| 12278 |
| 12279 if (map->prototype() != *prototype) { |
| 12280 Map::SetPrototype(map, prototype, FAST_PROTOTYPE); |
| 12281 } |
| 12282 |
| 12283 map->SetConstructor(*constructor); |
| 12284 return map; |
12261 } | 12285 } |
12262 | 12286 |
12263 // First create a new map with the size and number of in-object properties | 12287 Handle<JSFunction> new_target_function = Handle<JSFunction>::cast(new_target); |
12264 // suggested by the function. | |
12265 DCHECK(!new_target->shared()->is_generator()); | |
12266 DCHECK(!constructor->shared()->is_generator()); | |
12267 | 12288 |
12268 // Fetch or allocate prototype. | 12289 // Check that |new_target_function|'s initial map still in sync with |
12269 // TODO(verwaest): In case of non-instance prototype, use the | 12290 // the |constructor|, otherwise we must create a new initial map for |
12270 // intrinsicDefaultProto instead. | 12291 // |new_target_function|. |
12271 Handle<Object> prototype; | 12292 if (new_target_function->has_initial_map() && |
12272 if (new_target->has_instance_prototype()) { | 12293 new_target_function->initial_map()->GetConstructor() == *constructor) { |
12273 prototype = handle(new_target->instance_prototype(), isolate); | 12294 return handle(new_target_function->initial_map(), isolate); |
12274 } else { | |
12275 prototype = isolate->factory()->NewFunctionPrototype(new_target); | |
12276 } | 12295 } |
12277 | 12296 |
12278 // Finally link initial map and constructor function if the original | 12297 // Create a new map with the size and number of in-object properties suggested |
12279 // constructor is actually a subclass constructor. | 12298 // by the function. |
12280 if (IsSubclassConstructor(new_target->shared()->kind())) { | 12299 |
| 12300 // Link initial map and constructor function if the original constructor is |
| 12301 // actually a subclass constructor. |
| 12302 if (IsSubclassConstructor(new_target_function->shared()->kind())) { |
| 12303 Handle<Object> prototype(new_target_function->instance_prototype(), |
| 12304 isolate); |
12281 InstanceType instance_type = constructor_initial_map->instance_type(); | 12305 InstanceType instance_type = constructor_initial_map->instance_type(); |
12282 DCHECK(CanSubclassHaveInobjectProperties(instance_type)); | 12306 DCHECK(CanSubclassHaveInobjectProperties(instance_type)); |
12283 int internal_fields = | 12307 int internal_fields = |
12284 JSObject::GetInternalFieldCount(*constructor_initial_map); | 12308 JSObject::GetInternalFieldCount(*constructor_initial_map); |
12285 int pre_allocated = constructor_initial_map->GetInObjectProperties() - | 12309 int pre_allocated = constructor_initial_map->GetInObjectProperties() - |
12286 constructor_initial_map->unused_property_fields(); | 12310 constructor_initial_map->unused_property_fields(); |
12287 int instance_size; | 12311 int instance_size; |
12288 int in_object_properties; | 12312 int in_object_properties; |
12289 new_target->CalculateInstanceSizeForDerivedClass( | 12313 new_target_function->CalculateInstanceSizeForDerivedClass( |
12290 instance_type, internal_fields, &instance_size, &in_object_properties); | 12314 instance_type, internal_fields, &instance_size, &in_object_properties); |
12291 | 12315 |
12292 int unused_property_fields = in_object_properties - pre_allocated; | 12316 int unused_property_fields = in_object_properties - pre_allocated; |
12293 Handle<Map> map = | 12317 Handle<Map> map = |
12294 Map::CopyInitialMap(constructor_initial_map, instance_size, | 12318 Map::CopyInitialMap(constructor_initial_map, instance_size, |
12295 in_object_properties, unused_property_fields); | 12319 in_object_properties, unused_property_fields); |
12296 | 12320 |
12297 JSFunction::SetInitialMap(new_target, map, prototype); | 12321 JSFunction::SetInitialMap(new_target_function, map, prototype); |
12298 map->SetConstructor(*constructor); | 12322 map->SetConstructor(*constructor); |
12299 new_target->StartInobjectSlackTracking(); | 12323 new_target_function->StartInobjectSlackTracking(); |
12300 return map; | |
12301 | |
12302 } else { | |
12303 Handle<Map> map = Map::CopyInitialMap(constructor_initial_map); | |
12304 DCHECK(prototype->IsJSReceiver()); | |
12305 if (map->prototype() != *prototype) { | |
12306 Map::SetPrototype(map, prototype, FAST_PROTOTYPE); | |
12307 } | |
12308 map->SetConstructor(*constructor); | |
12309 return map; | 12324 return map; |
12310 } | 12325 } |
| 12326 |
| 12327 // Fetch the prototype. |
| 12328 Handle<Object> prototype; |
| 12329 if (new_target_function->map()->has_non_instance_prototype()) { |
| 12330 // TODO(verwaest): In case of non-instance prototype, use the |
| 12331 // intrinsicDefaultProto instead. |
| 12332 prototype = handle(new_target_function->context() |
| 12333 ->native_context() |
| 12334 ->initial_object_prototype()); |
| 12335 } else { |
| 12336 // Make sure the prototype is cached on new_target_function. |
| 12337 EnsureHasInitialMap(new_target_function); |
| 12338 prototype = handle(new_target_function->instance_prototype(), isolate); |
| 12339 } |
| 12340 |
| 12341 Handle<Map> map = Map::CopyInitialMap(constructor_initial_map); |
| 12342 DCHECK(prototype->IsJSReceiver()); |
| 12343 if (map->prototype() != *prototype) { |
| 12344 Map::SetPrototype(map, prototype, FAST_PROTOTYPE); |
| 12345 } |
| 12346 map->SetConstructor(*constructor); |
| 12347 return map; |
12311 } | 12348 } |
12312 | 12349 |
12313 | 12350 |
12314 void JSFunction::PrintName(FILE* out) { | 12351 void JSFunction::PrintName(FILE* out) { |
12315 base::SmartArrayPointer<char> name = shared()->DebugName()->ToCString(); | 12352 base::SmartArrayPointer<char> name = shared()->DebugName()->ToCString(); |
12316 PrintF(out, "%s", name.get()); | 12353 PrintF(out, "%s", name.get()); |
12317 } | 12354 } |
12318 | 12355 |
12319 | 12356 |
12320 // The filter is a pattern that matches function names in this way: | 12357 // The filter is a pattern that matches function names in this way: |
(...skipping 6326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
18647 if (cell->value() != *new_value) { | 18684 if (cell->value() != *new_value) { |
18648 cell->set_value(*new_value); | 18685 cell->set_value(*new_value); |
18649 Isolate* isolate = cell->GetIsolate(); | 18686 Isolate* isolate = cell->GetIsolate(); |
18650 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 18687 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
18651 isolate, DependentCode::kPropertyCellChangedGroup); | 18688 isolate, DependentCode::kPropertyCellChangedGroup); |
18652 } | 18689 } |
18653 } | 18690 } |
18654 | 18691 |
18655 } // namespace internal | 18692 } // namespace internal |
18656 } // namespace v8 | 18693 } // namespace v8 |
OLD | NEW |