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" |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 return native_context->iname(); | 149 return native_context->iname(); |
150 V8_INTRINSICS_LIST(GET_INTRINSIC_VALUE) | 150 V8_INTRINSICS_LIST(GET_INTRINSIC_VALUE) |
151 #undef GET_INTRINSIC_VALUE | 151 #undef GET_INTRINSIC_VALUE |
152 } | 152 } |
153 return nullptr; | 153 return nullptr; |
154 } | 154 } |
155 | 155 |
156 // Returns parent function template or null. | 156 // Returns parent function template or null. |
157 FunctionTemplateInfo* GetParent(FunctionTemplateInfo* data) { | 157 FunctionTemplateInfo* GetParent(FunctionTemplateInfo* data) { |
158 Object* parent = data->parent_template(); | 158 Object* parent = data->parent_template(); |
159 return parent->IsUndefined() ? nullptr : FunctionTemplateInfo::cast(parent); | 159 return parent->IsUndefined(data->GetIsolate()) |
| 160 ? nullptr |
| 161 : FunctionTemplateInfo::cast(parent); |
160 } | 162 } |
161 | 163 |
162 // Starting from given object template's constructor walk up the inheritance | 164 // Starting from given object template's constructor walk up the inheritance |
163 // chain till a function template that has an instance template is found. | 165 // chain till a function template that has an instance template is found. |
164 ObjectTemplateInfo* GetParent(ObjectTemplateInfo* data) { | 166 ObjectTemplateInfo* GetParent(ObjectTemplateInfo* data) { |
165 Object* maybe_ctor = data->constructor(); | 167 Object* maybe_ctor = data->constructor(); |
166 if (maybe_ctor->IsUndefined()) return nullptr; | 168 Isolate* isolate = data->GetIsolate(); |
| 169 if (maybe_ctor->IsUndefined(isolate)) return nullptr; |
167 FunctionTemplateInfo* ctor = FunctionTemplateInfo::cast(maybe_ctor); | 170 FunctionTemplateInfo* ctor = FunctionTemplateInfo::cast(maybe_ctor); |
168 while (true) { | 171 while (true) { |
169 ctor = GetParent(ctor); | 172 ctor = GetParent(ctor); |
170 if (ctor == nullptr) return nullptr; | 173 if (ctor == nullptr) return nullptr; |
171 Object* maybe_obj = ctor->instance_template(); | 174 Object* maybe_obj = ctor->instance_template(); |
172 if (!maybe_obj->IsUndefined()) return ObjectTemplateInfo::cast(maybe_obj); | 175 if (!maybe_obj->IsUndefined(isolate)) { |
| 176 return ObjectTemplateInfo::cast(maybe_obj); |
| 177 } |
173 } | 178 } |
174 } | 179 } |
175 | 180 |
176 template <typename TemplateInfoT> | 181 template <typename TemplateInfoT> |
177 MaybeHandle<JSObject> ConfigureInstance(Isolate* isolate, Handle<JSObject> obj, | 182 MaybeHandle<JSObject> ConfigureInstance(Isolate* isolate, Handle<JSObject> obj, |
178 Handle<TemplateInfoT> data, | 183 Handle<TemplateInfoT> data, |
179 bool is_hidden_prototype) { | 184 bool is_hidden_prototype) { |
180 HandleScope scope(isolate); | 185 HandleScope scope(isolate); |
181 // Disable access checks while instantiating the object. | 186 // Disable access checks while instantiating the object. |
182 AccessCheckDisableScope access_check_scope(isolate, obj); | 187 AccessCheckDisableScope access_check_scope(isolate, obj); |
183 | 188 |
184 // Walk the inheritance chain and copy all accessors to current object. | 189 // Walk the inheritance chain and copy all accessors to current object. |
185 int max_number_of_properties = 0; | 190 int max_number_of_properties = 0; |
186 TemplateInfoT* info = *data; | 191 TemplateInfoT* info = *data; |
187 while (info != nullptr) { | 192 while (info != nullptr) { |
188 if (!info->property_accessors()->IsUndefined()) { | 193 if (!info->property_accessors()->IsUndefined(isolate)) { |
189 Object* props = info->property_accessors(); | 194 Object* props = info->property_accessors(); |
190 if (!props->IsUndefined()) { | 195 if (!props->IsUndefined(isolate)) { |
191 Handle<Object> props_handle(props, isolate); | 196 Handle<Object> props_handle(props, isolate); |
192 NeanderArray props_array(props_handle); | 197 NeanderArray props_array(props_handle); |
193 max_number_of_properties += props_array.length(); | 198 max_number_of_properties += props_array.length(); |
194 } | 199 } |
195 } | 200 } |
196 info = GetParent(info); | 201 info = GetParent(info); |
197 } | 202 } |
198 | 203 |
199 if (max_number_of_properties > 0) { | 204 if (max_number_of_properties > 0) { |
200 int valid_descriptors = 0; | 205 int valid_descriptors = 0; |
201 // Use a temporary FixedArray to accumulate unique accessors. | 206 // Use a temporary FixedArray to accumulate unique accessors. |
202 Handle<FixedArray> array = | 207 Handle<FixedArray> array = |
203 isolate->factory()->NewFixedArray(max_number_of_properties); | 208 isolate->factory()->NewFixedArray(max_number_of_properties); |
204 | 209 |
205 info = *data; | 210 info = *data; |
206 while (info != nullptr) { | 211 while (info != nullptr) { |
207 // Accumulate accessors. | 212 // Accumulate accessors. |
208 if (!info->property_accessors()->IsUndefined()) { | 213 if (!info->property_accessors()->IsUndefined(isolate)) { |
209 Handle<Object> props(info->property_accessors(), isolate); | 214 Handle<Object> props(info->property_accessors(), isolate); |
210 valid_descriptors = | 215 valid_descriptors = |
211 AccessorInfo::AppendUnique(props, array, valid_descriptors); | 216 AccessorInfo::AppendUnique(props, array, valid_descriptors); |
212 } | 217 } |
213 info = GetParent(info); | 218 info = GetParent(info); |
214 } | 219 } |
215 | 220 |
216 // Install accumulated accessors. | 221 // Install accumulated accessors. |
217 for (int i = 0; i < valid_descriptors; i++) { | 222 for (int i = 0; i < valid_descriptors; i++) { |
218 Handle<AccessorInfo> accessor(AccessorInfo::cast(array->get(i))); | 223 Handle<AccessorInfo> accessor(AccessorInfo::cast(array->get(i))); |
219 JSObject::SetAccessor(obj, accessor).Assert(); | 224 JSObject::SetAccessor(obj, accessor).Assert(); |
220 } | 225 } |
221 } | 226 } |
222 | 227 |
223 auto property_list = handle(data->property_list(), isolate); | 228 auto property_list = handle(data->property_list(), isolate); |
224 if (property_list->IsUndefined()) return obj; | 229 if (property_list->IsUndefined(isolate)) return obj; |
225 // TODO(dcarney): just use a FixedArray here. | 230 // TODO(dcarney): just use a FixedArray here. |
226 NeanderArray properties(property_list); | 231 NeanderArray properties(property_list); |
227 if (properties.length() == 0) return obj; | 232 if (properties.length() == 0) return obj; |
228 | 233 |
229 int i = 0; | 234 int i = 0; |
230 for (int c = 0; c < data->number_of_properties(); c++) { | 235 for (int c = 0; c < data->number_of_properties(); c++) { |
231 auto name = handle(Name::cast(properties.get(i++)), isolate); | 236 auto name = handle(Name::cast(properties.get(i++)), isolate); |
232 auto bit = handle(properties.get(i++), isolate); | 237 auto bit = handle(properties.get(i++), isolate); |
233 if (bit->IsSmi()) { | 238 if (bit->IsSmi()) { |
234 PropertyDetails details(Smi::cast(*bit)); | 239 PropertyDetails details(Smi::cast(*bit)); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
316 Object* boilerplate = cache->ValueAt(entry); | 321 Object* boilerplate = cache->ValueAt(entry); |
317 result = handle(JSObject::cast(boilerplate), isolate); | 322 result = handle(JSObject::cast(boilerplate), isolate); |
318 return isolate->factory()->CopyJSObject(result); | 323 return isolate->factory()->CopyJSObject(result); |
319 } | 324 } |
320 } | 325 } |
321 // Enter a new scope. Recursion could otherwise create a lot of handles. | 326 // Enter a new scope. Recursion could otherwise create a lot of handles. |
322 HandleScope scope(isolate); | 327 HandleScope scope(isolate); |
323 | 328 |
324 if (constructor.is_null()) { | 329 if (constructor.is_null()) { |
325 Handle<Object> cons(info->constructor(), isolate); | 330 Handle<Object> cons(info->constructor(), isolate); |
326 if (cons->IsUndefined()) { | 331 if (cons->IsUndefined(isolate)) { |
327 constructor = isolate->object_function(); | 332 constructor = isolate->object_function(); |
328 } else { | 333 } else { |
329 auto cons_templ = Handle<FunctionTemplateInfo>::cast(cons); | 334 auto cons_templ = Handle<FunctionTemplateInfo>::cast(cons); |
330 ASSIGN_RETURN_ON_EXCEPTION(isolate, constructor, | 335 ASSIGN_RETURN_ON_EXCEPTION(isolate, constructor, |
331 InstantiateFunction(isolate, cons_templ), | 336 InstantiateFunction(isolate, cons_templ), |
332 JSObject); | 337 JSObject); |
333 } | 338 } |
334 | 339 |
335 if (new_target.is_null()) new_target = constructor; | 340 if (new_target.is_null()) new_target = constructor; |
336 } | 341 } |
(...skipping 27 matching lines...) Expand all Loading... |
364 if (entry != UnseededNumberDictionary::kNotFound) { | 369 if (entry != UnseededNumberDictionary::kNotFound) { |
365 Object* element = cache->ValueAt(entry); | 370 Object* element = cache->ValueAt(entry); |
366 return handle(JSFunction::cast(element), isolate); | 371 return handle(JSFunction::cast(element), isolate); |
367 } | 372 } |
368 } | 373 } |
369 // Enter a new scope. Recursion could otherwise create a lot of handles. | 374 // Enter a new scope. Recursion could otherwise create a lot of handles. |
370 HandleScope scope(isolate); | 375 HandleScope scope(isolate); |
371 Handle<JSObject> prototype; | 376 Handle<JSObject> prototype; |
372 if (!data->remove_prototype()) { | 377 if (!data->remove_prototype()) { |
373 auto prototype_templ = handle(data->prototype_template(), isolate); | 378 auto prototype_templ = handle(data->prototype_template(), isolate); |
374 if (prototype_templ->IsUndefined()) { | 379 if (prototype_templ->IsUndefined(isolate)) { |
375 prototype = isolate->factory()->NewJSObject(isolate->object_function()); | 380 prototype = isolate->factory()->NewJSObject(isolate->object_function()); |
376 } else { | 381 } else { |
377 ASSIGN_RETURN_ON_EXCEPTION( | 382 ASSIGN_RETURN_ON_EXCEPTION( |
378 isolate, prototype, | 383 isolate, prototype, |
379 InstantiateObject(isolate, | 384 InstantiateObject(isolate, |
380 Handle<ObjectTemplateInfo>::cast(prototype_templ), | 385 Handle<ObjectTemplateInfo>::cast(prototype_templ), |
381 Handle<JSReceiver>(), data->hidden_prototype()), | 386 Handle<JSReceiver>(), data->hidden_prototype()), |
382 JSFunction); | 387 JSFunction); |
383 } | 388 } |
384 auto parent = handle(data->parent_template(), isolate); | 389 auto parent = handle(data->parent_template(), isolate); |
385 if (!parent->IsUndefined()) { | 390 if (!parent->IsUndefined(isolate)) { |
386 Handle<JSFunction> parent_instance; | 391 Handle<JSFunction> parent_instance; |
387 ASSIGN_RETURN_ON_EXCEPTION( | 392 ASSIGN_RETURN_ON_EXCEPTION( |
388 isolate, parent_instance, | 393 isolate, parent_instance, |
389 InstantiateFunction(isolate, | 394 InstantiateFunction(isolate, |
390 Handle<FunctionTemplateInfo>::cast(parent)), | 395 Handle<FunctionTemplateInfo>::cast(parent)), |
391 JSFunction); | 396 JSFunction); |
392 // TODO(dcarney): decide what to do here. | 397 // TODO(dcarney): decide what to do here. |
393 Handle<Object> parent_prototype; | 398 Handle<Object> parent_prototype; |
394 ASSIGN_RETURN_ON_EXCEPTION( | 399 ASSIGN_RETURN_ON_EXCEPTION( |
395 isolate, parent_prototype, | 400 isolate, parent_prototype, |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 | 443 |
439 private: | 444 private: |
440 Isolate* isolate_; | 445 Isolate* isolate_; |
441 SaveContext save_context_; | 446 SaveContext save_context_; |
442 }; | 447 }; |
443 | 448 |
444 | 449 |
445 void AddPropertyToPropertyList(Isolate* isolate, Handle<TemplateInfo> templ, | 450 void AddPropertyToPropertyList(Isolate* isolate, Handle<TemplateInfo> templ, |
446 int length, Handle<Object>* data) { | 451 int length, Handle<Object>* data) { |
447 auto list = handle(templ->property_list(), isolate); | 452 auto list = handle(templ->property_list(), isolate); |
448 if (list->IsUndefined()) { | 453 if (list->IsUndefined(isolate)) { |
449 list = NeanderArray(isolate).value(); | 454 list = NeanderArray(isolate).value(); |
450 templ->set_property_list(*list); | 455 templ->set_property_list(*list); |
451 } | 456 } |
452 templ->set_number_of_properties(templ->number_of_properties() + 1); | 457 templ->set_number_of_properties(templ->number_of_properties() + 1); |
453 NeanderArray array(list); | 458 NeanderArray array(list); |
454 for (int i = 0; i < length; i++) { | 459 for (int i = 0; i < length; i++) { |
455 Handle<Object> value = | 460 Handle<Object> value = |
456 data[i].is_null() | 461 data[i].is_null() |
457 ? Handle<Object>::cast(isolate->factory()->undefined_value()) | 462 ? Handle<Object>::cast(isolate->factory()->undefined_value()) |
458 : data[i]; | 463 : data[i]; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
513 auto details_handle = handle(details.AsSmi(), isolate); | 518 auto details_handle = handle(details.AsSmi(), isolate); |
514 Handle<Object> data[kSize] = {name, details_handle, getter, setter}; | 519 Handle<Object> data[kSize] = {name, details_handle, getter, setter}; |
515 AddPropertyToPropertyList(isolate, info, kSize, data); | 520 AddPropertyToPropertyList(isolate, info, kSize, data); |
516 } | 521 } |
517 | 522 |
518 | 523 |
519 void ApiNatives::AddNativeDataProperty(Isolate* isolate, | 524 void ApiNatives::AddNativeDataProperty(Isolate* isolate, |
520 Handle<TemplateInfo> info, | 525 Handle<TemplateInfo> info, |
521 Handle<AccessorInfo> property) { | 526 Handle<AccessorInfo> property) { |
522 auto list = handle(info->property_accessors(), isolate); | 527 auto list = handle(info->property_accessors(), isolate); |
523 if (list->IsUndefined()) { | 528 if (list->IsUndefined(isolate)) { |
524 list = NeanderArray(isolate).value(); | 529 list = NeanderArray(isolate).value(); |
525 info->set_property_accessors(*list); | 530 info->set_property_accessors(*list); |
526 } | 531 } |
527 NeanderArray array(list); | 532 NeanderArray array(list); |
528 array.add(isolate, property); | 533 array.add(isolate, property); |
529 } | 534 } |
530 | 535 |
531 | 536 |
532 Handle<JSFunction> ApiNatives::CreateApiFunction( | 537 Handle<JSFunction> ApiNatives::CreateApiFunction( |
533 Isolate* isolate, Handle<FunctionTemplateInfo> obj, | 538 Isolate* isolate, Handle<FunctionTemplateInfo> obj, |
534 Handle<Object> prototype, ApiInstanceType instance_type) { | 539 Handle<Object> prototype, ApiInstanceType instance_type) { |
535 Handle<Code> code; | 540 Handle<Code> code; |
536 if (obj->call_code()->IsCallHandlerInfo() && | 541 if (obj->call_code()->IsCallHandlerInfo() && |
537 CallHandlerInfo::cast(obj->call_code())->fast_handler()->IsCode()) { | 542 CallHandlerInfo::cast(obj->call_code())->fast_handler()->IsCode()) { |
538 code = isolate->builtins()->HandleFastApiCall(); | 543 code = isolate->builtins()->HandleFastApiCall(); |
539 } else { | 544 } else { |
540 code = isolate->builtins()->HandleApiCall(); | 545 code = isolate->builtins()->HandleApiCall(); |
541 } | 546 } |
542 Handle<Code> construct_stub = | 547 Handle<Code> construct_stub = |
543 prototype.is_null() ? isolate->builtins()->ConstructedNonConstructable() | 548 prototype.is_null() ? isolate->builtins()->ConstructedNonConstructable() |
544 : isolate->builtins()->JSConstructStubApi(); | 549 : isolate->builtins()->JSConstructStubApi(); |
545 | 550 |
546 obj->set_instantiated(true); | 551 obj->set_instantiated(true); |
547 Handle<JSFunction> result; | 552 Handle<JSFunction> result; |
548 if (obj->remove_prototype()) { | 553 if (obj->remove_prototype()) { |
549 result = isolate->factory()->NewFunctionWithoutPrototype( | 554 result = isolate->factory()->NewFunctionWithoutPrototype( |
550 isolate->factory()->empty_string(), code); | 555 isolate->factory()->empty_string(), code); |
551 } else { | 556 } else { |
552 int internal_field_count = 0; | 557 int internal_field_count = 0; |
553 if (!obj->instance_template()->IsUndefined()) { | 558 if (!obj->instance_template()->IsUndefined(isolate)) { |
554 Handle<ObjectTemplateInfo> instance_template = Handle<ObjectTemplateInfo>( | 559 Handle<ObjectTemplateInfo> instance_template = Handle<ObjectTemplateInfo>( |
555 ObjectTemplateInfo::cast(obj->instance_template())); | 560 ObjectTemplateInfo::cast(obj->instance_template())); |
556 internal_field_count = | 561 internal_field_count = |
557 Smi::cast(instance_template->internal_field_count())->value(); | 562 Smi::cast(instance_template->internal_field_count())->value(); |
558 } | 563 } |
559 | 564 |
560 // TODO(svenpanne) Kill ApiInstanceType and refactor things by generalizing | 565 // TODO(svenpanne) Kill ApiInstanceType and refactor things by generalizing |
561 // JSObject::GetHeaderSize. | 566 // JSObject::GetHeaderSize. |
562 int instance_size = kPointerSize * internal_field_count; | 567 int instance_size = kPointerSize * internal_field_count; |
563 InstanceType type; | 568 InstanceType type; |
564 switch (instance_type) { | 569 switch (instance_type) { |
565 case JavaScriptObjectType: | 570 case JavaScriptObjectType: |
566 if (!obj->needs_access_check() && | 571 if (!obj->needs_access_check() && |
567 obj->named_property_handler()->IsUndefined() && | 572 obj->named_property_handler()->IsUndefined(isolate) && |
568 obj->indexed_property_handler()->IsUndefined()) { | 573 obj->indexed_property_handler()->IsUndefined(isolate)) { |
569 type = JS_API_OBJECT_TYPE; | 574 type = JS_API_OBJECT_TYPE; |
570 } else { | 575 } else { |
571 type = JS_SPECIAL_API_OBJECT_TYPE; | 576 type = JS_SPECIAL_API_OBJECT_TYPE; |
572 } | 577 } |
573 instance_size += JSObject::kHeaderSize; | 578 instance_size += JSObject::kHeaderSize; |
574 break; | 579 break; |
575 case GlobalObjectType: | 580 case GlobalObjectType: |
576 type = JS_GLOBAL_OBJECT_TYPE; | 581 type = JS_GLOBAL_OBJECT_TYPE; |
577 instance_size += JSGlobalObject::kSize; | 582 instance_size += JSGlobalObject::kSize; |
578 break; | 583 break; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
626 if (obj->undetectable()) { | 631 if (obj->undetectable()) { |
627 map->set_is_undetectable(); | 632 map->set_is_undetectable(); |
628 } | 633 } |
629 | 634 |
630 // Mark as needs_access_check if needed. | 635 // Mark as needs_access_check if needed. |
631 if (obj->needs_access_check()) { | 636 if (obj->needs_access_check()) { |
632 map->set_is_access_check_needed(true); | 637 map->set_is_access_check_needed(true); |
633 } | 638 } |
634 | 639 |
635 // Set interceptor information in the map. | 640 // Set interceptor information in the map. |
636 if (!obj->named_property_handler()->IsUndefined()) { | 641 if (!obj->named_property_handler()->IsUndefined(isolate)) { |
637 map->set_has_named_interceptor(); | 642 map->set_has_named_interceptor(); |
638 } | 643 } |
639 if (!obj->indexed_property_handler()->IsUndefined()) { | 644 if (!obj->indexed_property_handler()->IsUndefined(isolate)) { |
640 map->set_has_indexed_interceptor(); | 645 map->set_has_indexed_interceptor(); |
641 } | 646 } |
642 | 647 |
643 // Mark instance as callable in the map. | 648 // Mark instance as callable in the map. |
644 if (!obj->instance_call_handler()->IsUndefined()) { | 649 if (!obj->instance_call_handler()->IsUndefined(isolate)) { |
645 map->set_is_callable(); | 650 map->set_is_callable(); |
646 map->set_is_constructor(true); | 651 map->set_is_constructor(true); |
647 } | 652 } |
648 | 653 |
649 DCHECK(result->shared()->IsApiFunction()); | 654 DCHECK(result->shared()->IsApiFunction()); |
650 return result; | 655 return result; |
651 } | 656 } |
652 | 657 |
653 } // namespace internal | 658 } // namespace internal |
654 } // namespace v8 | 659 } // namespace v8 |
OLD | NEW |