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