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 |