| 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 class InvokeScope { |
| 19 public: |
| 20 explicit InvokeScope(Isolate* isolate) |
| 21 : isolate_(isolate), save_context_(isolate) {} |
| 22 ~InvokeScope() { |
| 23 bool has_exception = isolate_->has_pending_exception(); |
| 24 if (has_exception) { |
| 25 isolate_->ReportPendingMessages(); |
| 26 } else { |
| 27 isolate_->clear_pending_message(); |
| 28 } |
| 29 } |
| 30 |
| 31 private: |
| 32 Isolate* isolate_; |
| 33 SaveContext save_context_; |
| 34 }; |
| 35 |
| 18 MaybeHandle<JSObject> InstantiateObject(Isolate* isolate, | 36 MaybeHandle<JSObject> InstantiateObject(Isolate* isolate, |
| 19 Handle<ObjectTemplateInfo> data, | 37 Handle<ObjectTemplateInfo> data, |
| 20 Handle<JSReceiver> new_target, | 38 Handle<JSReceiver> new_target, |
| 21 bool is_hidden_prototype); | 39 bool is_hidden_prototype); |
| 22 | 40 |
| 23 MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate, | 41 MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate, |
| 24 Handle<FunctionTemplateInfo> data, | 42 Handle<FunctionTemplateInfo> data, |
| 25 Handle<Name> name = Handle<Name>()); | 43 Handle<Name> name = Handle<Name>()); |
| 26 | 44 |
| 27 | 45 |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 switch (intrinsic) { | 164 switch (intrinsic) { |
| 147 #define GET_INTRINSIC_VALUE(name, iname) \ | 165 #define GET_INTRINSIC_VALUE(name, iname) \ |
| 148 case v8::k##name: \ | 166 case v8::k##name: \ |
| 149 return native_context->iname(); | 167 return native_context->iname(); |
| 150 V8_INTRINSICS_LIST(GET_INTRINSIC_VALUE) | 168 V8_INTRINSICS_LIST(GET_INTRINSIC_VALUE) |
| 151 #undef GET_INTRINSIC_VALUE | 169 #undef GET_INTRINSIC_VALUE |
| 152 } | 170 } |
| 153 return nullptr; | 171 return nullptr; |
| 154 } | 172 } |
| 155 | 173 |
| 156 // Returns parent function template or null. | |
| 157 FunctionTemplateInfo* GetParent(FunctionTemplateInfo* data) { | |
| 158 Object* parent = data->parent_template(); | |
| 159 return parent->IsUndefined(data->GetIsolate()) | |
| 160 ? nullptr | |
| 161 : FunctionTemplateInfo::cast(parent); | |
| 162 } | |
| 163 | |
| 164 // Starting from given object template's constructor walk up the inheritance | |
| 165 // chain till a function template that has an instance template is found. | |
| 166 ObjectTemplateInfo* GetParent(ObjectTemplateInfo* data) { | |
| 167 Object* maybe_ctor = data->constructor(); | |
| 168 Isolate* isolate = data->GetIsolate(); | |
| 169 if (maybe_ctor->IsUndefined(isolate)) return nullptr; | |
| 170 FunctionTemplateInfo* ctor = FunctionTemplateInfo::cast(maybe_ctor); | |
| 171 while (true) { | |
| 172 ctor = GetParent(ctor); | |
| 173 if (ctor == nullptr) return nullptr; | |
| 174 Object* maybe_obj = ctor->instance_template(); | |
| 175 if (!maybe_obj->IsUndefined(isolate)) { | |
| 176 return ObjectTemplateInfo::cast(maybe_obj); | |
| 177 } | |
| 178 } | |
| 179 } | |
| 180 | 174 |
| 181 template <typename TemplateInfoT> | 175 template <typename TemplateInfoT> |
| 182 MaybeHandle<JSObject> ConfigureInstance(Isolate* isolate, Handle<JSObject> obj, | 176 MaybeHandle<JSObject> ConfigureInstance(Isolate* isolate, Handle<JSObject> obj, |
| 183 Handle<TemplateInfoT> data, | 177 Handle<TemplateInfoT> data, |
| 184 bool is_hidden_prototype) { | 178 bool is_hidden_prototype) { |
| 185 HandleScope scope(isolate); | 179 HandleScope scope(isolate); |
| 186 // Disable access checks while instantiating the object. | 180 // Disable access checks while instantiating the object. |
| 187 AccessCheckDisableScope access_check_scope(isolate, obj); | 181 AccessCheckDisableScope access_check_scope(isolate, obj); |
| 188 | 182 |
| 189 // Walk the inheritance chain and copy all accessors to current object. | 183 // Walk the inheritance chain and copy all accessors to current object. |
| 190 int max_number_of_properties = 0; | 184 int max_number_of_properties = 0; |
| 191 TemplateInfoT* info = *data; | 185 TemplateInfoT* info = *data; |
| 192 while (info != nullptr) { | 186 while (info != nullptr) { |
| 193 if (!info->property_accessors()->IsUndefined(isolate)) { | 187 if (!info->property_accessors()->IsUndefined(isolate)) { |
| 194 Object* props = info->property_accessors(); | 188 Object* props = info->property_accessors(); |
| 195 if (!props->IsUndefined(isolate)) { | 189 if (!props->IsUndefined(isolate)) { |
| 196 Handle<Object> props_handle(props, isolate); | 190 Handle<Object> props_handle(props, isolate); |
| 197 NeanderArray props_array(props_handle); | 191 NeanderArray props_array(props_handle); |
| 198 max_number_of_properties += props_array.length(); | 192 max_number_of_properties += props_array.length(); |
| 199 } | 193 } |
| 200 } | 194 } |
| 201 info = GetParent(info); | 195 info = info->GetParent(isolate); |
| 202 } | 196 } |
| 203 | 197 |
| 204 if (max_number_of_properties > 0) { | 198 if (max_number_of_properties > 0) { |
| 205 int valid_descriptors = 0; | 199 int valid_descriptors = 0; |
| 206 // Use a temporary FixedArray to accumulate unique accessors. | 200 // Use a temporary FixedArray to accumulate unique accessors. |
| 207 Handle<FixedArray> array = | 201 Handle<FixedArray> array = |
| 208 isolate->factory()->NewFixedArray(max_number_of_properties); | 202 isolate->factory()->NewFixedArray(max_number_of_properties); |
| 209 | 203 |
| 210 info = *data; | 204 info = *data; |
| 211 while (info != nullptr) { | 205 while (info != nullptr) { |
| 212 // Accumulate accessors. | 206 // Accumulate accessors. |
| 213 if (!info->property_accessors()->IsUndefined(isolate)) { | 207 if (!info->property_accessors()->IsUndefined(isolate)) { |
| 214 Handle<Object> props(info->property_accessors(), isolate); | 208 Handle<Object> props(info->property_accessors(), isolate); |
| 215 valid_descriptors = | 209 valid_descriptors = |
| 216 AccessorInfo::AppendUnique(props, array, valid_descriptors); | 210 AccessorInfo::AppendUnique(props, array, valid_descriptors); |
| 217 } | 211 } |
| 218 info = GetParent(info); | 212 info = info->GetParent(isolate); |
| 219 } | 213 } |
| 220 | 214 |
| 221 // Install accumulated accessors. | 215 // Install accumulated accessors. |
| 222 for (int i = 0; i < valid_descriptors; i++) { | 216 for (int i = 0; i < valid_descriptors; i++) { |
| 223 Handle<AccessorInfo> accessor(AccessorInfo::cast(array->get(i))); | 217 Handle<AccessorInfo> accessor(AccessorInfo::cast(array->get(i))); |
| 224 JSObject::SetAccessor(obj, accessor).Assert(); | 218 JSObject::SetAccessor(obj, accessor).Assert(); |
| 225 } | 219 } |
| 226 } | 220 } |
| 227 | 221 |
| 228 auto property_list = handle(data->property_list(), isolate); | 222 auto property_list = handle(data->property_list(), isolate); |
| 229 if (property_list->IsUndefined(isolate)) return obj; | 223 if (property_list->IsUndefined(isolate)) return obj; |
| 230 // TODO(dcarney): just use a FixedArray here. | 224 // TODO(dcarney): just use a FixedArray here. |
| 231 NeanderArray properties(property_list); | 225 NeanderArray properties(property_list); |
| 232 if (properties.length() == 0) return obj; | 226 if (properties.length() == 0) return obj; |
| 233 | 227 |
| 234 int i = 0; | 228 int i = 0; |
| 235 for (int c = 0; c < data->number_of_properties(); c++) { | 229 for (int c = 0; c < data->number_of_properties(); c++) { |
| 236 auto name = handle(Name::cast(properties.get(i++)), isolate); | 230 auto name = handle(Name::cast(properties.get(i++)), isolate); |
| 237 auto bit = handle(properties.get(i++), isolate); | 231 Object* bit = properties.get(i++); |
| 238 if (bit->IsSmi()) { | 232 if (bit->IsSmi()) { |
| 239 PropertyDetails details(Smi::cast(*bit)); | 233 PropertyDetails details(Smi::cast(bit)); |
| 240 PropertyAttributes attributes = details.attributes(); | 234 PropertyAttributes attributes = details.attributes(); |
| 241 PropertyKind kind = details.kind(); | 235 PropertyKind kind = details.kind(); |
| 242 | 236 |
| 243 if (kind == kData) { | 237 if (kind == kData) { |
| 244 auto prop_data = handle(properties.get(i++), isolate); | 238 auto prop_data = handle(properties.get(i++), isolate); |
| 245 RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name, | 239 RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name, |
| 246 prop_data, attributes), | 240 prop_data, attributes), |
| 247 JSObject); | 241 JSObject); |
| 248 } else { | 242 } else { |
| 249 auto getter = handle(properties.get(i++), isolate); | 243 auto getter = handle(properties.get(i++), isolate); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 265 auto prop_data = handle(GetIntrinsic(isolate, intrinsic), isolate); | 259 auto prop_data = handle(GetIntrinsic(isolate, intrinsic), isolate); |
| 266 | 260 |
| 267 RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name, | 261 RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name, |
| 268 prop_data, attributes), | 262 prop_data, attributes), |
| 269 JSObject); | 263 JSObject); |
| 270 } | 264 } |
| 271 } | 265 } |
| 272 return obj; | 266 return obj; |
| 273 } | 267 } |
| 274 | 268 |
| 275 void CacheTemplateInstantiation(Isolate* isolate, uint32_t serial_number, | 269 MaybeHandle<JSObject> ProbeInstantiationsCache(Isolate* isolate, |
| 276 Handle<JSObject> object) { | 270 int serial_number) { |
| 277 auto cache = isolate->template_instantiations_cache(); | 271 DCHECK_LE(1, serial_number); |
| 278 auto new_cache = | 272 if (serial_number <= TemplateInfo::kFastTemplateInstantiationsCacheSize) { |
| 279 UnseededNumberDictionary::AtNumberPut(cache, serial_number, object); | 273 Handle<FixedArray> fast_cache = |
| 280 isolate->native_context()->set_template_instantiations_cache(*new_cache); | 274 isolate->fast_template_instantiations_cache(); |
| 275 return fast_cache->GetValue<JSObject>(isolate, serial_number - 1); |
| 276 } else { |
| 277 Handle<UnseededNumberDictionary> slow_cache = |
| 278 isolate->slow_template_instantiations_cache(); |
| 279 int entry = slow_cache->FindEntry(serial_number); |
| 280 if (entry == UnseededNumberDictionary::kNotFound) { |
| 281 return MaybeHandle<JSObject>(); |
| 282 } |
| 283 return handle(JSObject::cast(slow_cache->ValueAt(entry)), isolate); |
| 284 } |
| 281 } | 285 } |
| 282 | 286 |
| 283 void UncacheTemplateInstantiation(Isolate* isolate, uint32_t serial_number) { | 287 void CacheTemplateInstantiation(Isolate* isolate, int serial_number, |
| 284 auto cache = isolate->template_instantiations_cache(); | 288 Handle<JSObject> object) { |
| 285 int entry = cache->FindEntry(serial_number); | 289 DCHECK_LE(1, serial_number); |
| 286 DCHECK(entry != UnseededNumberDictionary::kNotFound); | 290 if (serial_number <= TemplateInfo::kFastTemplateInstantiationsCacheSize) { |
| 287 Handle<Object> result = | 291 Handle<FixedArray> fast_cache = |
| 288 UnseededNumberDictionary::DeleteProperty(cache, entry); | 292 isolate->fast_template_instantiations_cache(); |
| 289 USE(result); | 293 Handle<FixedArray> new_cache = |
| 290 DCHECK(result->IsTrue(isolate)); | 294 FixedArray::SetAndGrow(fast_cache, serial_number - 1, object); |
| 291 auto new_cache = UnseededNumberDictionary::Shrink(cache, entry); | 295 if (*new_cache != *fast_cache) { |
| 292 isolate->native_context()->set_template_instantiations_cache(*new_cache); | 296 isolate->native_context()->set_fast_template_instantiations_cache( |
| 297 *new_cache); |
| 298 } |
| 299 } else { |
| 300 Handle<UnseededNumberDictionary> cache = |
| 301 isolate->slow_template_instantiations_cache(); |
| 302 auto new_cache = |
| 303 UnseededNumberDictionary::AtNumberPut(cache, serial_number, object); |
| 304 if (*new_cache != *cache) { |
| 305 isolate->native_context()->set_slow_template_instantiations_cache( |
| 306 *new_cache); |
| 307 } |
| 308 } |
| 309 } |
| 310 |
| 311 void UncacheTemplateInstantiation(Isolate* isolate, int serial_number) { |
| 312 DCHECK_LE(1, serial_number); |
| 313 if (serial_number <= TemplateInfo::kFastTemplateInstantiationsCacheSize) { |
| 314 Handle<FixedArray> fast_cache = |
| 315 isolate->fast_template_instantiations_cache(); |
| 316 DCHECK(!fast_cache->get(serial_number - 1)->IsUndefined(isolate)); |
| 317 fast_cache->set_undefined(serial_number - 1); |
| 318 } else { |
| 319 Handle<UnseededNumberDictionary> cache = |
| 320 isolate->slow_template_instantiations_cache(); |
| 321 int entry = cache->FindEntry(serial_number); |
| 322 DCHECK(entry != UnseededNumberDictionary::kNotFound); |
| 323 Handle<Object> result = |
| 324 UnseededNumberDictionary::DeleteProperty(cache, entry); |
| 325 USE(result); |
| 326 DCHECK(result->IsTrue(isolate)); |
| 327 auto new_cache = UnseededNumberDictionary::Shrink(cache, entry); |
| 328 isolate->native_context()->set_slow_template_instantiations_cache( |
| 329 *new_cache); |
| 330 } |
| 331 } |
| 332 |
| 333 bool IsSimpleInstantiation(Isolate* isolate, ObjectTemplateInfo* info, |
| 334 JSReceiver* new_target) { |
| 335 DisallowHeapAllocation no_gc; |
| 336 |
| 337 if (!new_target->IsJSFunction()) return false; |
| 338 JSFunction* fun = JSFunction::cast(new_target); |
| 339 if (fun->shared()->function_data() != info->constructor()) return false; |
| 340 if (info->immutable_proto()) return false; |
| 341 return fun->context()->native_context() != |
| 342 isolate->context()->native_context(); |
| 293 } | 343 } |
| 294 | 344 |
| 295 MaybeHandle<JSObject> InstantiateObject(Isolate* isolate, | 345 MaybeHandle<JSObject> InstantiateObject(Isolate* isolate, |
| 296 Handle<ObjectTemplateInfo> info, | 346 Handle<ObjectTemplateInfo> info, |
| 297 Handle<JSReceiver> new_target, | 347 Handle<JSReceiver> new_target, |
| 298 bool is_hidden_prototype) { | 348 bool is_hidden_prototype) { |
| 299 Handle<JSFunction> constructor; | 349 Handle<JSFunction> constructor; |
| 300 uint32_t serial_number = | 350 int serial_number = Smi::cast(info->serial_number())->value(); |
| 301 static_cast<uint32_t>(Smi::cast(info->serial_number())->value()); | |
| 302 if (!new_target.is_null()) { | 351 if (!new_target.is_null()) { |
| 303 if (new_target->IsJSFunction() && | 352 if (IsSimpleInstantiation(isolate, *info, *new_target)) { |
| 304 JSFunction::cast(*new_target)->shared()->function_data() == | |
| 305 info->constructor() && | |
| 306 JSFunction::cast(*new_target)->context()->native_context() == | |
| 307 isolate->context()->native_context() && | |
| 308 !info->immutable_proto()) { | |
| 309 constructor = Handle<JSFunction>::cast(new_target); | 353 constructor = Handle<JSFunction>::cast(new_target); |
| 310 } else { | 354 } else { |
| 311 // Disable caching for subclass instantiation. | 355 // Disable caching for subclass instantiation. |
| 312 serial_number = 0; | 356 serial_number = 0; |
| 313 } | 357 } |
| 314 } | 358 } |
| 315 // Fast path. | 359 // Fast path. |
| 316 Handle<JSObject> result; | 360 Handle<JSObject> result; |
| 317 if (serial_number) { | 361 if (serial_number) { |
| 318 // Probe cache. | 362 if (ProbeInstantiationsCache(isolate, serial_number).ToHandle(&result)) { |
| 319 auto cache = isolate->template_instantiations_cache(); | |
| 320 int entry = cache->FindEntry(serial_number); | |
| 321 if (entry != UnseededNumberDictionary::kNotFound) { | |
| 322 Object* boilerplate = cache->ValueAt(entry); | |
| 323 result = handle(JSObject::cast(boilerplate), isolate); | |
| 324 return isolate->factory()->CopyJSObject(result); | 363 return isolate->factory()->CopyJSObject(result); |
| 325 } | 364 } |
| 326 } | 365 } |
| 327 // Enter a new scope. Recursion could otherwise create a lot of handles. | |
| 328 HandleScope scope(isolate); | |
| 329 | 366 |
| 330 if (constructor.is_null()) { | 367 if (constructor.is_null()) { |
| 331 Handle<Object> cons(info->constructor(), isolate); | 368 Object* maybe_constructor_info = info->constructor(); |
| 332 if (cons->IsUndefined(isolate)) { | 369 if (maybe_constructor_info->IsUndefined(isolate)) { |
| 333 constructor = isolate->object_function(); | 370 constructor = isolate->object_function(); |
| 334 } else { | 371 } else { |
| 335 auto cons_templ = Handle<FunctionTemplateInfo>::cast(cons); | 372 // Enter a new scope. Recursion could otherwise create a lot of handles. |
| 336 ASSIGN_RETURN_ON_EXCEPTION(isolate, constructor, | 373 HandleScope scope(isolate); |
| 374 Handle<FunctionTemplateInfo> cons_templ( |
| 375 FunctionTemplateInfo::cast(maybe_constructor_info), isolate); |
| 376 Handle<JSFunction> tmp_constructor; |
| 377 ASSIGN_RETURN_ON_EXCEPTION(isolate, tmp_constructor, |
| 337 InstantiateFunction(isolate, cons_templ), | 378 InstantiateFunction(isolate, cons_templ), |
| 338 JSObject); | 379 JSObject); |
| 380 constructor = scope.CloseAndEscape(tmp_constructor); |
| 339 } | 381 } |
| 340 | 382 |
| 341 if (new_target.is_null()) new_target = constructor; | 383 if (new_target.is_null()) new_target = constructor; |
| 342 } | 384 } |
| 343 | 385 |
| 344 Handle<JSObject> object; | 386 Handle<JSObject> object; |
| 345 ASSIGN_RETURN_ON_EXCEPTION(isolate, object, | 387 ASSIGN_RETURN_ON_EXCEPTION(isolate, object, |
| 346 JSObject::New(constructor, new_target), JSObject); | 388 JSObject::New(constructor, new_target), JSObject); |
| 347 ASSIGN_RETURN_ON_EXCEPTION( | 389 ASSIGN_RETURN_ON_EXCEPTION( |
| 348 isolate, result, | 390 isolate, result, |
| 349 ConfigureInstance(isolate, object, info, is_hidden_prototype), JSObject); | 391 ConfigureInstance(isolate, object, info, is_hidden_prototype), JSObject); |
| 350 if (info->immutable_proto()) { | 392 if (info->immutable_proto()) { |
| 351 JSObject::SetImmutableProto(object); | 393 JSObject::SetImmutableProto(object); |
| 352 } | 394 } |
| 353 // TODO(dcarney): is this necessary? | 395 // TODO(dcarney): is this necessary? |
| 354 JSObject::MigrateSlowToFast(result, 0, "ApiNatives::InstantiateObject"); | 396 JSObject::MigrateSlowToFast(result, 0, "ApiNatives::InstantiateObject"); |
| 355 | 397 |
| 356 if (serial_number) { | 398 if (serial_number) { |
| 357 CacheTemplateInstantiation(isolate, serial_number, result); | 399 CacheTemplateInstantiation(isolate, serial_number, result); |
| 358 result = isolate->factory()->CopyJSObject(result); | 400 result = isolate->factory()->CopyJSObject(result); |
| 359 } | 401 } |
| 360 return scope.CloseAndEscape(result); | 402 return result; |
| 361 } | 403 } |
| 362 | 404 |
| 363 | 405 |
| 364 MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate, | 406 MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate, |
| 365 Handle<FunctionTemplateInfo> data, | 407 Handle<FunctionTemplateInfo> data, |
| 366 Handle<Name> name) { | 408 Handle<Name> name) { |
| 367 uint32_t serial_number = | 409 int serial_number = Smi::cast(data->serial_number())->value(); |
| 368 static_cast<uint32_t>(Smi::cast(data->serial_number())->value()); | |
| 369 if (serial_number) { | 410 if (serial_number) { |
| 370 // Probe cache. | 411 Handle<JSObject> result; |
| 371 auto cache = isolate->template_instantiations_cache(); | 412 if (ProbeInstantiationsCache(isolate, serial_number).ToHandle(&result)) { |
| 372 int entry = cache->FindEntry(serial_number); | 413 return Handle<JSFunction>::cast(result); |
| 373 if (entry != UnseededNumberDictionary::kNotFound) { | |
| 374 Object* element = cache->ValueAt(entry); | |
| 375 return handle(JSFunction::cast(element), isolate); | |
| 376 } | 414 } |
| 377 } | 415 } |
| 378 // Enter a new scope. Recursion could otherwise create a lot of handles. | |
| 379 HandleScope scope(isolate); | |
| 380 Handle<JSObject> prototype; | 416 Handle<JSObject> prototype; |
| 381 if (!data->remove_prototype()) { | 417 if (!data->remove_prototype()) { |
| 382 auto prototype_templ = handle(data->prototype_template(), isolate); | 418 Object* prototype_templ = data->prototype_template(); |
| 383 if (prototype_templ->IsUndefined(isolate)) { | 419 if (prototype_templ->IsUndefined(isolate)) { |
| 384 prototype = isolate->factory()->NewJSObject(isolate->object_function()); | 420 prototype = isolate->factory()->NewJSObject(isolate->object_function()); |
| 385 } else { | 421 } else { |
| 386 ASSIGN_RETURN_ON_EXCEPTION( | 422 ASSIGN_RETURN_ON_EXCEPTION( |
| 387 isolate, prototype, | 423 isolate, prototype, |
| 388 InstantiateObject(isolate, | 424 InstantiateObject( |
| 389 Handle<ObjectTemplateInfo>::cast(prototype_templ), | 425 isolate, |
| 390 Handle<JSReceiver>(), data->hidden_prototype()), | 426 handle(ObjectTemplateInfo::cast(prototype_templ), isolate), |
| 427 Handle<JSReceiver>(), data->hidden_prototype()), |
| 391 JSFunction); | 428 JSFunction); |
| 392 } | 429 } |
| 393 auto parent = handle(data->parent_template(), isolate); | 430 Object* parent = data->parent_template(); |
| 394 if (!parent->IsUndefined(isolate)) { | 431 if (!parent->IsUndefined(isolate)) { |
| 432 // Enter a new scope. Recursion could otherwise create a lot of handles. |
| 433 HandleScope scope(isolate); |
| 395 Handle<JSFunction> parent_instance; | 434 Handle<JSFunction> parent_instance; |
| 396 ASSIGN_RETURN_ON_EXCEPTION( | 435 ASSIGN_RETURN_ON_EXCEPTION( |
| 397 isolate, parent_instance, | 436 isolate, parent_instance, |
| 398 InstantiateFunction(isolate, | 437 InstantiateFunction( |
| 399 Handle<FunctionTemplateInfo>::cast(parent)), | 438 isolate, handle(FunctionTemplateInfo::cast(parent), isolate)), |
| 400 JSFunction); | 439 JSFunction); |
| 401 // TODO(dcarney): decide what to do here. | 440 // TODO(dcarney): decide what to do here. |
| 402 Handle<Object> parent_prototype; | 441 Handle<Object> parent_prototype; |
| 403 ASSIGN_RETURN_ON_EXCEPTION( | 442 ASSIGN_RETURN_ON_EXCEPTION( |
| 404 isolate, parent_prototype, | 443 isolate, parent_prototype, |
| 405 JSObject::GetProperty(parent_instance, | 444 JSObject::GetProperty(parent_instance, |
| 406 isolate->factory()->prototype_string()), | 445 isolate->factory()->prototype_string()), |
| 407 JSFunction); | 446 JSFunction); |
| 408 MAYBE_RETURN(JSObject::SetPrototype(prototype, parent_prototype, false, | 447 MAYBE_RETURN(JSObject::SetPrototype(prototype, parent_prototype, false, |
| 409 Object::THROW_ON_ERROR), | 448 Object::THROW_ON_ERROR), |
| 410 MaybeHandle<JSFunction>()); | 449 MaybeHandle<JSFunction>()); |
| 411 } | 450 } |
| 412 } | 451 } |
| 413 auto function = ApiNatives::CreateApiFunction( | 452 Handle<JSFunction> function = ApiNatives::CreateApiFunction( |
| 414 isolate, data, prototype, ApiNatives::JavaScriptObjectType); | 453 isolate, data, prototype, ApiNatives::JavaScriptObjectType); |
| 415 if (!name.is_null() && name->IsString()) { | 454 if (!name.is_null() && name->IsString()) { |
| 416 function->shared()->set_name(*name); | 455 function->shared()->set_name(*name); |
| 417 } | 456 } |
| 418 if (serial_number) { | 457 if (serial_number) { |
| 419 // Cache the function. | 458 // Cache the function. |
| 420 CacheTemplateInstantiation(isolate, serial_number, function); | 459 CacheTemplateInstantiation(isolate, serial_number, function); |
| 421 } | 460 } |
| 422 auto result = | 461 MaybeHandle<JSObject> result = |
| 423 ConfigureInstance(isolate, function, data, data->hidden_prototype()); | 462 ConfigureInstance(isolate, function, data, data->hidden_prototype()); |
| 424 if (result.is_null()) { | 463 if (result.is_null()) { |
| 425 // Uncache on error. | 464 // Uncache on error. |
| 426 if (serial_number) { | 465 if (serial_number) { |
| 427 UncacheTemplateInstantiation(isolate, serial_number); | 466 UncacheTemplateInstantiation(isolate, serial_number); |
| 428 } | 467 } |
| 429 return MaybeHandle<JSFunction>(); | 468 return MaybeHandle<JSFunction>(); |
| 430 } | 469 } |
| 431 return scope.CloseAndEscape(function); | 470 return function; |
| 432 } | 471 } |
| 433 | 472 |
| 434 | 473 |
| 435 class InvokeScope { | |
| 436 public: | |
| 437 explicit InvokeScope(Isolate* isolate) | |
| 438 : isolate_(isolate), save_context_(isolate) {} | |
| 439 ~InvokeScope() { | |
| 440 bool has_exception = isolate_->has_pending_exception(); | |
| 441 if (has_exception) { | |
| 442 isolate_->ReportPendingMessages(); | |
| 443 } else { | |
| 444 isolate_->clear_pending_message(); | |
| 445 } | |
| 446 } | |
| 447 | |
| 448 private: | |
| 449 Isolate* isolate_; | |
| 450 SaveContext save_context_; | |
| 451 }; | |
| 452 | |
| 453 | |
| 454 void AddPropertyToPropertyList(Isolate* isolate, Handle<TemplateInfo> templ, | 474 void AddPropertyToPropertyList(Isolate* isolate, Handle<TemplateInfo> templ, |
| 455 int length, Handle<Object>* data) { | 475 int length, Handle<Object>* data) { |
| 456 auto list = handle(templ->property_list(), isolate); | 476 auto list = handle(templ->property_list(), isolate); |
| 457 if (list->IsUndefined(isolate)) { | 477 if (list->IsUndefined(isolate)) { |
| 458 list = NeanderArray(isolate).value(); | 478 list = NeanderArray(isolate).value(); |
| 459 templ->set_property_list(*list); | 479 templ->set_property_list(*list); |
| 460 } | 480 } |
| 461 templ->set_number_of_properties(templ->number_of_properties() + 1); | 481 templ->set_number_of_properties(templ->number_of_properties() + 1); |
| 462 NeanderArray array(list); | 482 NeanderArray array(list); |
| 463 for (int i = 0; i < length; i++) { | 483 for (int i = 0; i < length; i++) { |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 663 if (!obj->instance_call_handler()->IsUndefined(isolate)) { | 683 if (!obj->instance_call_handler()->IsUndefined(isolate)) { |
| 664 map->set_is_callable(); | 684 map->set_is_callable(); |
| 665 map->set_is_constructor(true); | 685 map->set_is_constructor(true); |
| 666 } | 686 } |
| 667 | 687 |
| 668 return result; | 688 return result; |
| 669 } | 689 } |
| 670 | 690 |
| 671 } // namespace internal | 691 } // namespace internal |
| 672 } // namespace v8 | 692 } // namespace v8 |
| OLD | NEW |