| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/api-natives.h" | 5 #include "src/api-natives.h" |
| 6 | 6 |
| 7 #include "src/api.h" | 7 #include "src/api.h" |
| 8 #include "src/isolate-inl.h" | 8 #include "src/isolate-inl.h" |
| 9 #include "src/lookup.h" | 9 #include "src/lookup.h" |
| 10 #include "src/messages.h" | 10 #include "src/messages.h" |
| 11 | 11 |
| 12 namespace v8 { | 12 namespace v8 { |
| 13 namespace internal { | 13 namespace internal { |
| 14 | 14 |
| 15 | 15 |
| 16 namespace { | 16 namespace { |
| 17 | 17 |
| 18 MaybeHandle<JSObject> InstantiateObject(Isolate* isolate, | 18 MaybeHandle<JSObject> InstantiateObject(Isolate* isolate, |
| 19 Handle<ObjectTemplateInfo> data); | 19 Handle<ObjectTemplateInfo> data, |
| 20 | 20 bool is_hidden_prototype); |
| 21 | 21 |
| 22 MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate, | 22 MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate, |
| 23 Handle<FunctionTemplateInfo> data, | 23 Handle<FunctionTemplateInfo> data, |
| 24 Handle<Name> name = Handle<Name>()); | 24 Handle<Name> name = Handle<Name>()); |
| 25 | 25 |
| 26 | 26 |
| 27 MaybeHandle<Object> Instantiate(Isolate* isolate, Handle<Object> data, | 27 MaybeHandle<Object> Instantiate(Isolate* isolate, Handle<Object> data, |
| 28 Handle<Name> name = Handle<Name>()) { | 28 Handle<Name> name = Handle<Name>()) { |
| 29 if (data->IsFunctionTemplateInfo()) { | 29 if (data->IsFunctionTemplateInfo()) { |
| 30 return InstantiateFunction(isolate, | 30 return InstantiateFunction(isolate, |
| 31 Handle<FunctionTemplateInfo>::cast(data), name); | 31 Handle<FunctionTemplateInfo>::cast(data), name); |
| 32 } else if (data->IsObjectTemplateInfo()) { | 32 } else if (data->IsObjectTemplateInfo()) { |
| 33 return InstantiateObject(isolate, Handle<ObjectTemplateInfo>::cast(data)); | 33 return InstantiateObject(isolate, Handle<ObjectTemplateInfo>::cast(data), |
| 34 false); |
| 34 } else { | 35 } else { |
| 35 return data; | 36 return data; |
| 36 } | 37 } |
| 37 } | 38 } |
| 38 | 39 |
| 39 | 40 MaybeHandle<Object> DefineAccessorProperty( |
| 40 MaybeHandle<Object> DefineAccessorProperty(Isolate* isolate, | 41 Isolate* isolate, Handle<JSObject> object, Handle<Name> name, |
| 41 Handle<JSObject> object, | 42 Handle<Object> getter, Handle<Object> setter, PropertyAttributes attributes, |
| 42 Handle<Name> name, | 43 bool force_instantiate) { |
| 43 Handle<Object> getter, | 44 DCHECK(!getter->IsFunctionTemplateInfo() || |
| 44 Handle<Object> setter, | 45 !FunctionTemplateInfo::cast(*getter)->do_not_cache()); |
| 45 PropertyAttributes attributes) { | 46 DCHECK(!setter->IsFunctionTemplateInfo() || |
| 46 if (!getter->IsUndefined()) { | 47 !FunctionTemplateInfo::cast(*setter)->do_not_cache()); |
| 47 ASSIGN_RETURN_ON_EXCEPTION( | 48 if (force_instantiate) { |
| 48 isolate, getter, | 49 if (getter->IsFunctionTemplateInfo()) { |
| 49 InstantiateFunction(isolate, | 50 ASSIGN_RETURN_ON_EXCEPTION( |
| 50 Handle<FunctionTemplateInfo>::cast(getter)), | 51 isolate, getter, |
| 51 Object); | 52 InstantiateFunction(isolate, |
| 52 } | 53 Handle<FunctionTemplateInfo>::cast(getter)), |
| 53 if (!setter->IsUndefined()) { | 54 Object); |
| 54 ASSIGN_RETURN_ON_EXCEPTION( | 55 } |
| 55 isolate, setter, | 56 if (setter->IsFunctionTemplateInfo()) { |
| 56 InstantiateFunction(isolate, | 57 ASSIGN_RETURN_ON_EXCEPTION( |
| 57 Handle<FunctionTemplateInfo>::cast(setter)), | 58 isolate, setter, |
| 58 Object); | 59 InstantiateFunction(isolate, |
| 60 Handle<FunctionTemplateInfo>::cast(setter)), |
| 61 Object); |
| 62 } |
| 59 } | 63 } |
| 60 RETURN_ON_EXCEPTION(isolate, JSObject::DefineAccessor(object, name, getter, | 64 RETURN_ON_EXCEPTION(isolate, JSObject::DefineAccessor(object, name, getter, |
| 61 setter, attributes), | 65 setter, attributes), |
| 62 Object); | 66 Object); |
| 63 return object; | 67 return object; |
| 64 } | 68 } |
| 65 | 69 |
| 66 | 70 |
| 67 MaybeHandle<Object> DefineDataProperty(Isolate* isolate, | 71 MaybeHandle<Object> DefineDataProperty(Isolate* isolate, |
| 68 Handle<JSObject> object, | 72 Handle<JSObject> object, |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 while (true) { | 167 while (true) { |
| 164 ctor = GetParent(ctor); | 168 ctor = GetParent(ctor); |
| 165 if (ctor == nullptr) return nullptr; | 169 if (ctor == nullptr) return nullptr; |
| 166 Object* maybe_obj = ctor->instance_template(); | 170 Object* maybe_obj = ctor->instance_template(); |
| 167 if (!maybe_obj->IsUndefined()) return ObjectTemplateInfo::cast(maybe_obj); | 171 if (!maybe_obj->IsUndefined()) return ObjectTemplateInfo::cast(maybe_obj); |
| 168 } | 172 } |
| 169 } | 173 } |
| 170 | 174 |
| 171 template <typename TemplateInfoT> | 175 template <typename TemplateInfoT> |
| 172 MaybeHandle<JSObject> ConfigureInstance(Isolate* isolate, Handle<JSObject> obj, | 176 MaybeHandle<JSObject> ConfigureInstance(Isolate* isolate, Handle<JSObject> obj, |
| 173 Handle<TemplateInfoT> data) { | 177 Handle<TemplateInfoT> data, |
| 178 bool is_hidden_prototype) { |
| 174 HandleScope scope(isolate); | 179 HandleScope scope(isolate); |
| 175 // Disable access checks while instantiating the object. | 180 // Disable access checks while instantiating the object. |
| 176 AccessCheckDisableScope access_check_scope(isolate, obj); | 181 AccessCheckDisableScope access_check_scope(isolate, obj); |
| 177 | 182 |
| 178 // Walk the inheritance chain and copy all accessors to current object. | 183 // Walk the inheritance chain and copy all accessors to current object. |
| 179 int max_number_of_properties = 0; | 184 int max_number_of_properties = 0; |
| 180 TemplateInfoT* info = *data; | 185 TemplateInfoT* info = *data; |
| 181 while (info != nullptr) { | 186 while (info != nullptr) { |
| 182 if (!info->property_accessors()->IsUndefined()) { | 187 if (!info->property_accessors()->IsUndefined()) { |
| 183 Object* props = info->property_accessors(); | 188 Object* props = info->property_accessors(); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 PropertyKind kind = details.kind(); | 235 PropertyKind kind = details.kind(); |
| 231 | 236 |
| 232 if (kind == kData) { | 237 if (kind == kData) { |
| 233 auto prop_data = handle(properties.get(i++), isolate); | 238 auto prop_data = handle(properties.get(i++), isolate); |
| 234 RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name, | 239 RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name, |
| 235 prop_data, attributes), | 240 prop_data, attributes), |
| 236 JSObject); | 241 JSObject); |
| 237 } else { | 242 } else { |
| 238 auto getter = handle(properties.get(i++), isolate); | 243 auto getter = handle(properties.get(i++), isolate); |
| 239 auto setter = handle(properties.get(i++), isolate); | 244 auto setter = handle(properties.get(i++), isolate); |
| 240 RETURN_ON_EXCEPTION(isolate, | 245 RETURN_ON_EXCEPTION( |
| 241 DefineAccessorProperty(isolate, obj, name, getter, | 246 isolate, DefineAccessorProperty(isolate, obj, name, getter, setter, |
| 242 setter, attributes), | 247 attributes, is_hidden_prototype), |
| 243 JSObject); | 248 JSObject); |
| 244 } | 249 } |
| 245 } else { | 250 } else { |
| 246 // Intrinsic data property --- Get appropriate value from the current | 251 // Intrinsic data property --- Get appropriate value from the current |
| 247 // context. | 252 // context. |
| 248 PropertyDetails details(Smi::cast(properties.get(i++))); | 253 PropertyDetails details(Smi::cast(properties.get(i++))); |
| 249 PropertyAttributes attributes = details.attributes(); | 254 PropertyAttributes attributes = details.attributes(); |
| 250 DCHECK_EQ(kData, details.kind()); | 255 DCHECK_EQ(kData, details.kind()); |
| 251 | 256 |
| 252 v8::Intrinsic intrinsic = | 257 v8::Intrinsic intrinsic = |
| 253 static_cast<v8::Intrinsic>(Smi::cast(properties.get(i++))->value()); | 258 static_cast<v8::Intrinsic>(Smi::cast(properties.get(i++))->value()); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 270 | 275 |
| 271 void UncacheTemplateInstantiation(Isolate* isolate, Handle<Smi> serial_number) { | 276 void UncacheTemplateInstantiation(Isolate* isolate, Handle<Smi> serial_number) { |
| 272 auto cache = isolate->template_instantiations_cache(); | 277 auto cache = isolate->template_instantiations_cache(); |
| 273 bool was_present = false; | 278 bool was_present = false; |
| 274 auto new_cache = ObjectHashTable::Remove(cache, serial_number, &was_present); | 279 auto new_cache = ObjectHashTable::Remove(cache, serial_number, &was_present); |
| 275 DCHECK(was_present); | 280 DCHECK(was_present); |
| 276 isolate->native_context()->set_template_instantiations_cache(*new_cache); | 281 isolate->native_context()->set_template_instantiations_cache(*new_cache); |
| 277 } | 282 } |
| 278 | 283 |
| 279 MaybeHandle<JSObject> InstantiateObject(Isolate* isolate, | 284 MaybeHandle<JSObject> InstantiateObject(Isolate* isolate, |
| 280 Handle<ObjectTemplateInfo> info) { | 285 Handle<ObjectTemplateInfo> info, |
| 286 bool is_hidden_prototype) { |
| 281 // Enter a new scope. Recursion could otherwise create a lot of handles. | 287 // Enter a new scope. Recursion could otherwise create a lot of handles. |
| 282 HandleScope scope(isolate); | 288 HandleScope scope(isolate); |
| 283 // Fast path. | 289 // Fast path. |
| 284 Handle<JSObject> result; | 290 Handle<JSObject> result; |
| 285 auto constructor = handle(info->constructor(), isolate); | 291 auto constructor = handle(info->constructor(), isolate); |
| 286 Handle<JSFunction> cons; | 292 Handle<JSFunction> cons; |
| 287 if (constructor->IsUndefined()) { | 293 if (constructor->IsUndefined()) { |
| 288 cons = isolate->object_function(); | 294 cons = isolate->object_function(); |
| 289 } else { | 295 } else { |
| 290 auto cons_templ = Handle<FunctionTemplateInfo>::cast(constructor); | 296 auto cons_templ = Handle<FunctionTemplateInfo>::cast(constructor); |
| 291 ASSIGN_RETURN_ON_EXCEPTION( | 297 ASSIGN_RETURN_ON_EXCEPTION( |
| 292 isolate, cons, InstantiateFunction(isolate, cons_templ), JSFunction); | 298 isolate, cons, InstantiateFunction(isolate, cons_templ), JSFunction); |
| 293 } | 299 } |
| 294 auto serial_number = handle(Smi::cast(info->serial_number()), isolate); | 300 auto serial_number = handle(Smi::cast(info->serial_number()), isolate); |
| 295 if (serial_number->value()) { | 301 if (serial_number->value()) { |
| 296 // Probe cache. | 302 // Probe cache. |
| 297 auto cache = isolate->template_instantiations_cache(); | 303 auto cache = isolate->template_instantiations_cache(); |
| 298 Object* boilerplate = cache->Lookup(serial_number); | 304 Object* boilerplate = cache->Lookup(serial_number); |
| 299 if (boilerplate->IsJSObject()) { | 305 if (boilerplate->IsJSObject()) { |
| 300 result = handle(JSObject::cast(boilerplate), isolate); | 306 result = handle(JSObject::cast(boilerplate), isolate); |
| 301 ASSIGN_RETURN_ON_EXCEPTION( | 307 ASSIGN_RETURN_ON_EXCEPTION( |
| 302 isolate, result, JSObject::DeepCopyApiBoilerplate(result), JSObject); | 308 isolate, result, JSObject::DeepCopyApiBoilerplate(result), JSObject); |
| 303 return scope.CloseAndEscape(result); | 309 return scope.CloseAndEscape(result); |
| 304 } | 310 } |
| 305 } | 311 } |
| 306 auto object = isolate->factory()->NewJSObject(cons); | 312 auto object = isolate->factory()->NewJSObject(cons); |
| 307 ASSIGN_RETURN_ON_EXCEPTION( | 313 ASSIGN_RETURN_ON_EXCEPTION( |
| 308 isolate, result, ConfigureInstance(isolate, object, info), JSFunction); | 314 isolate, result, |
| 315 ConfigureInstance(isolate, object, info, is_hidden_prototype), |
| 316 JSFunction); |
| 309 // TODO(dcarney): is this necessary? | 317 // TODO(dcarney): is this necessary? |
| 310 JSObject::MigrateSlowToFast(result, 0, "ApiNatives::InstantiateObject"); | 318 JSObject::MigrateSlowToFast(result, 0, "ApiNatives::InstantiateObject"); |
| 311 | 319 |
| 312 if (serial_number->value()) { | 320 if (serial_number->value()) { |
| 313 CacheTemplateInstantiation(isolate, serial_number, result); | 321 CacheTemplateInstantiation(isolate, serial_number, result); |
| 314 ASSIGN_RETURN_ON_EXCEPTION( | 322 ASSIGN_RETURN_ON_EXCEPTION( |
| 315 isolate, result, JSObject::DeepCopyApiBoilerplate(result), JSObject); | 323 isolate, result, JSObject::DeepCopyApiBoilerplate(result), JSObject); |
| 316 } | 324 } |
| 317 return scope.CloseAndEscape(result); | 325 return scope.CloseAndEscape(result); |
| 318 } | 326 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 334 HandleScope scope(isolate); | 342 HandleScope scope(isolate); |
| 335 Handle<JSObject> prototype; | 343 Handle<JSObject> prototype; |
| 336 if (!data->remove_prototype()) { | 344 if (!data->remove_prototype()) { |
| 337 auto prototype_templ = handle(data->prototype_template(), isolate); | 345 auto prototype_templ = handle(data->prototype_template(), isolate); |
| 338 if (prototype_templ->IsUndefined()) { | 346 if (prototype_templ->IsUndefined()) { |
| 339 prototype = isolate->factory()->NewJSObject(isolate->object_function()); | 347 prototype = isolate->factory()->NewJSObject(isolate->object_function()); |
| 340 } else { | 348 } else { |
| 341 ASSIGN_RETURN_ON_EXCEPTION( | 349 ASSIGN_RETURN_ON_EXCEPTION( |
| 342 isolate, prototype, | 350 isolate, prototype, |
| 343 InstantiateObject(isolate, | 351 InstantiateObject(isolate, |
| 344 Handle<ObjectTemplateInfo>::cast(prototype_templ)), | 352 Handle<ObjectTemplateInfo>::cast(prototype_templ), |
| 353 data->hidden_prototype()), |
| 345 JSFunction); | 354 JSFunction); |
| 346 } | 355 } |
| 347 auto parent = handle(data->parent_template(), isolate); | 356 auto parent = handle(data->parent_template(), isolate); |
| 348 if (!parent->IsUndefined()) { | 357 if (!parent->IsUndefined()) { |
| 349 Handle<JSFunction> parent_instance; | 358 Handle<JSFunction> parent_instance; |
| 350 ASSIGN_RETURN_ON_EXCEPTION( | 359 ASSIGN_RETURN_ON_EXCEPTION( |
| 351 isolate, parent_instance, | 360 isolate, parent_instance, |
| 352 InstantiateFunction(isolate, | 361 InstantiateFunction(isolate, |
| 353 Handle<FunctionTemplateInfo>::cast(parent)), | 362 Handle<FunctionTemplateInfo>::cast(parent)), |
| 354 JSFunction); | 363 JSFunction); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 366 } | 375 } |
| 367 auto function = ApiNatives::CreateApiFunction( | 376 auto function = ApiNatives::CreateApiFunction( |
| 368 isolate, data, prototype, ApiNatives::JavaScriptObjectType); | 377 isolate, data, prototype, ApiNatives::JavaScriptObjectType); |
| 369 if (!name.is_null() && name->IsString()) { | 378 if (!name.is_null() && name->IsString()) { |
| 370 function->shared()->set_name(*name); | 379 function->shared()->set_name(*name); |
| 371 } | 380 } |
| 372 if (serial_number->value()) { | 381 if (serial_number->value()) { |
| 373 // Cache the function. | 382 // Cache the function. |
| 374 CacheTemplateInstantiation(isolate, serial_number, function); | 383 CacheTemplateInstantiation(isolate, serial_number, function); |
| 375 } | 384 } |
| 376 auto result = ConfigureInstance(isolate, function, data); | 385 auto result = |
| 386 ConfigureInstance(isolate, function, data, data->hidden_prototype()); |
| 377 if (result.is_null()) { | 387 if (result.is_null()) { |
| 378 // Uncache on error. | 388 // Uncache on error. |
| 379 if (serial_number->value()) { | 389 if (serial_number->value()) { |
| 380 UncacheTemplateInstantiation(isolate, serial_number); | 390 UncacheTemplateInstantiation(isolate, serial_number); |
| 381 } | 391 } |
| 382 return MaybeHandle<JSFunction>(); | 392 return MaybeHandle<JSFunction>(); |
| 383 } | 393 } |
| 384 return scope.CloseAndEscape(function); | 394 return scope.CloseAndEscape(function); |
| 385 } | 395 } |
| 386 | 396 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 430 Isolate* isolate = data->GetIsolate(); | 440 Isolate* isolate = data->GetIsolate(); |
| 431 InvokeScope invoke_scope(isolate); | 441 InvokeScope invoke_scope(isolate); |
| 432 return ::v8::internal::InstantiateFunction(isolate, data); | 442 return ::v8::internal::InstantiateFunction(isolate, data); |
| 433 } | 443 } |
| 434 | 444 |
| 435 | 445 |
| 436 MaybeHandle<JSObject> ApiNatives::InstantiateObject( | 446 MaybeHandle<JSObject> ApiNatives::InstantiateObject( |
| 437 Handle<ObjectTemplateInfo> data) { | 447 Handle<ObjectTemplateInfo> data) { |
| 438 Isolate* isolate = data->GetIsolate(); | 448 Isolate* isolate = data->GetIsolate(); |
| 439 InvokeScope invoke_scope(isolate); | 449 InvokeScope invoke_scope(isolate); |
| 440 return ::v8::internal::InstantiateObject(isolate, data); | 450 return ::v8::internal::InstantiateObject(isolate, data, false); |
| 441 } | 451 } |
| 442 | 452 |
| 443 | 453 |
| 444 void ApiNatives::AddDataProperty(Isolate* isolate, Handle<TemplateInfo> info, | 454 void ApiNatives::AddDataProperty(Isolate* isolate, Handle<TemplateInfo> info, |
| 445 Handle<Name> name, Handle<Object> value, | 455 Handle<Name> name, Handle<Object> value, |
| 446 PropertyAttributes attributes) { | 456 PropertyAttributes attributes) { |
| 447 const int kSize = 3; | 457 const int kSize = 3; |
| 448 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); | 458 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); |
| 449 auto details_handle = handle(details.AsSmi(), isolate); | 459 auto details_handle = handle(details.AsSmi(), isolate); |
| 450 Handle<Object> data[kSize] = {name, details_handle, value}; | 460 Handle<Object> data[kSize] = {name, details_handle, value}; |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 607 map->set_is_callable(); | 617 map->set_is_callable(); |
| 608 map->set_is_constructor(true); | 618 map->set_is_constructor(true); |
| 609 } | 619 } |
| 610 | 620 |
| 611 DCHECK(result->shared()->IsApiFunction()); | 621 DCHECK(result->shared()->IsApiFunction()); |
| 612 return result; | 622 return result; |
| 613 } | 623 } |
| 614 | 624 |
| 615 } // namespace internal | 625 } // namespace internal |
| 616 } // namespace v8 | 626 } // namespace v8 |
| OLD | NEW |