| 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 |