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