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 |