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