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 |