1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/execution.h"
6
7 #include "src/bootstrapper.h"
8 #include "src/codegen.h"
9 #include "src/deoptimizer.h"
10 #include "src/isolate-inl.h"
11 #include "src/vm-state-inl.h"
12
13 namespace v8 {
14 namespace internal {
15
StackGuard()16 StackGuard::StackGuard()
17 : isolate_(NULL) {
18 }
19
20
set_interrupt_limits(const ExecutionAccess & lock)21 void StackGuard::set_interrupt_limits(const ExecutionAccess& lock) {
22 DCHECK(isolate_ != NULL);
23 thread_local_.jslimit_ = kInterruptLimit;
24 thread_local_.climit_ = kInterruptLimit;
25 isolate_->heap()->SetStackLimits();
26 }
27
28
reset_limits(const ExecutionAccess & lock)29 void StackGuard::reset_limits(const ExecutionAccess& lock) {
30 DCHECK(isolate_ != NULL);
31 thread_local_.jslimit_ = thread_local_.real_jslimit_;
32 thread_local_.climit_ = thread_local_.real_climit_;
33 isolate_->heap()->SetStackLimits();
34 }
35
36
Invoke(bool is_construct,Handle<JSFunction> function,Handle<Object> receiver,int argc,Handle<Object> args[])37 MUST_USE_RESULT static MaybeHandle<Object> Invoke(
38 bool is_construct,
39 Handle<JSFunction> function,
40 Handle<Object> receiver,
41 int argc,
42 Handle<Object> args[]) {
43 Isolate* isolate = function->GetIsolate();
44
45 // Entering JavaScript.
46 VMState<JS> state(isolate);
47 CHECK(AllowJavascriptExecution::IsAllowed(isolate));
48 if (!ThrowOnJavascriptExecution::IsAllowed(isolate)) {
49 isolate->ThrowIllegalOperation();
50 isolate->ReportPendingMessages();
51 return MaybeHandle<Object>();
52 }
53
54 // Placeholder for return value.
55 Object* value = NULL;
56
57 typedef Object* (*JSEntryFunction)(byte* entry,
58 Object* function,
59 Object* receiver,
60 int argc,
61 Object*** args);
62
63 Handle<Code> code = is_construct
64 ? isolate->factory()->js_construct_entry_code()
65 : isolate->factory()->js_entry_code();
66
67 // Convert calls on global objects to be calls on the global
68 // receiver instead to avoid having a 'this' pointer which refers
69 // directly to a global object.
70 if (receiver->IsGlobalObject()) {
71 receiver = handle(Handle<GlobalObject>::cast(receiver)->global_proxy());
72 }
73
74 // Make sure that the global object of the context we're about to
75 // make the current one is indeed a global object.
76 DCHECK(function->context()->global_object()->IsGlobalObject());
77
78 {
79 // Save and restore context around invocation and block the
80 // allocation of handles without explicit handle scopes.
81 SaveContext save(isolate);
82 SealHandleScope shs(isolate);
83 JSEntryFunction stub_entry = FUNCTION_CAST<JSEntryFunction>(code->entry());
84
85 // Call the function through the right JS entry stub.
86 byte* function_entry = function->code()->entry();
87 JSFunction* func = *function;
88 Object* recv = *receiver;
89 Object*** argv = reinterpret_cast<Object***>(args);
90 value =
91 CALL_GENERATED_CODE(stub_entry, function_entry, func, recv, argc, argv);
92 }
93
94 #ifdef VERIFY_HEAP
95 value->ObjectVerify();
96 #endif
97
98 // Update the pending exception flag and return the value.
99 bool has_exception = value->IsException();
100 DCHECK(has_exception == isolate->has_pending_exception());
101 if (has_exception) {
102 isolate->ReportPendingMessages();
103 // Reset stepping state when script exits with uncaught exception.
104 if (isolate->debug()->is_active()) {
105 isolate->debug()->ClearStepping();
106 }
107 return MaybeHandle<Object>();
108 } else {
109 isolate->clear_pending_message();
110 }
111
112 return Handle<Object>(value, isolate);
113 }
114
115
Call(Isolate * isolate,Handle<Object> callable,Handle<Object> receiver,int argc,Handle<Object> argv[],bool convert_receiver)116 MaybeHandle<Object> Execution::Call(Isolate* isolate,
117 Handle<Object> callable,
118 Handle<Object> receiver,
119 int argc,
120 Handle<Object> argv[],
121 bool convert_receiver) {
122 if (!callable->IsJSFunction()) {
123 ASSIGN_RETURN_ON_EXCEPTION(
124 isolate, callable, TryGetFunctionDelegate(isolate, callable), Object);
125 }
126 Handle<JSFunction> func = Handle<JSFunction>::cast(callable);
127
128 // In sloppy mode, convert receiver.
129 if (convert_receiver && !receiver->IsJSReceiver() &&
130 !func->shared()->native() &&
131 func->shared()->strict_mode() == SLOPPY) {
132 if (receiver->IsUndefined() || receiver->IsNull()) {
133 receiver = handle(func->global_proxy());
134 DCHECK(!receiver->IsJSBuiltinsObject());
135 } else {
136 ASSIGN_RETURN_ON_EXCEPTION(
137 isolate, receiver, ToObject(isolate, receiver), Object);
138 }
139 }
140
141 return Invoke(false, func, receiver, argc, argv);
142 }
143
144
New(Handle<JSFunction> func,int argc,Handle<Object> argv[])145 MaybeHandle<Object> Execution::New(Handle<JSFunction> func,
146 int argc,
147 Handle<Object> argv[]) {
148 return Invoke(true, func, handle(func->global_proxy()), argc, argv);
149 }
150
151
TryCall(Handle<JSFunction> func,Handle<Object> receiver,int argc,Handle<Object> args[],MaybeHandle<Object> * exception_out)152 MaybeHandle<Object> Execution::TryCall(Handle<JSFunction> func,
153 Handle<Object> receiver, int argc,
154 Handle<Object> args[],
155 MaybeHandle<Object>* exception_out) {
156 bool is_termination = false;
157 Isolate* isolate = func->GetIsolate();
158 MaybeHandle<Object> maybe_result;
159 if (exception_out != NULL) *exception_out = MaybeHandle<Object>();
160 // Enter a try-block while executing the JavaScript code. To avoid
161 // duplicate error printing it must be non-verbose. Also, to avoid
162 // creating message objects during stack overflow we shouldn't
163 // capture messages.
164 {
165 v8::TryCatch catcher;
166 catcher.SetVerbose(false);
167 catcher.SetCaptureMessage(false);
168
169 maybe_result = Invoke(false, func, receiver, argc, args);
170
171 if (maybe_result.is_null()) {
172 DCHECK(catcher.HasCaught());
173 DCHECK(isolate->has_pending_exception());
174 DCHECK(isolate->external_caught_exception());
175 if (exception_out != NULL) {
176 if (isolate->pending_exception() ==
177 isolate->heap()->termination_exception()) {
178 is_termination = true;
179 } else {
180 *exception_out = v8::Utils::OpenHandle(*catcher.Exception());
181 }
182 }
183 isolate->OptionalRescheduleException(true);
184 }
185
186 DCHECK(!isolate->has_pending_exception());
187 DCHECK(!isolate->external_caught_exception());
188 }
189 if (is_termination) isolate->TerminateExecution();
190 return maybe_result;
191 }
192
193
GetFunctionDelegate(Isolate * isolate,Handle<Object> object)194 Handle<Object> Execution::GetFunctionDelegate(Isolate* isolate,
195 Handle<Object> object) {
196 DCHECK(!object->IsJSFunction());
197 Factory* factory = isolate->factory();
198
199 // If you return a function from here, it will be called when an
200 // attempt is made to call the given object as a function.
201
202 // If object is a function proxy, get its handler. Iterate if necessary.
203 Object* fun = *object;
204 while (fun->IsJSFunctionProxy()) {
205 fun = JSFunctionProxy::cast(fun)->call_trap();
206 }
207 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
208
209 // Objects created through the API can have an instance-call handler
210 // that should be used when calling the object as a function.
211 if (fun->IsHeapObject() &&
212 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
213 return Handle<JSFunction>(
214 isolate->native_context()->call_as_function_delegate());
215 }
216
217 return factory->undefined_value();
218 }
219
220
TryGetFunctionDelegate(Isolate * isolate,Handle<Object> object)221 MaybeHandle<Object> Execution::TryGetFunctionDelegate(Isolate* isolate,
222 Handle<Object> object) {
223 DCHECK(!object->IsJSFunction());
224
225 // If object is a function proxy, get its handler. Iterate if necessary.
226 Object* fun = *object;
227 while (fun->IsJSFunctionProxy()) {
228 fun = JSFunctionProxy::cast(fun)->call_trap();
229 }
230 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
231
232 // Objects created through the API can have an instance-call handler
233 // that should be used when calling the object as a function.
234 if (fun->IsHeapObject() &&
235 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
236 return Handle<JSFunction>(
237 isolate->native_context()->call_as_function_delegate());
238 }
239
240 // If the Object doesn't have an instance-call handler we should
241 // throw a non-callable exception.
242 THROW_NEW_ERROR(isolate, NewTypeError("called_non_callable",
243 i::HandleVector<i::Object>(&object, 1)),
244 Object);
245 }
246
247
GetConstructorDelegate(Isolate * isolate,Handle<Object> object)248 Handle<Object> Execution::GetConstructorDelegate(Isolate* isolate,
249 Handle<Object> object) {
250 DCHECK(!object->IsJSFunction());
251
252 // If you return a function from here, it will be called when an
253 // attempt is made to call the given object as a constructor.
254
255 // If object is a function proxies, get its handler. Iterate if necessary.
256 Object* fun = *object;
257 while (fun->IsJSFunctionProxy()) {
258 fun = JSFunctionProxy::cast(fun)->call_trap();
259 }
260 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
261
262 // Objects created through the API can have an instance-call handler
263 // that should be used when calling the object as a function.
264 if (fun->IsHeapObject() &&
265 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
266 return Handle<JSFunction>(
267 isolate->native_context()->call_as_constructor_delegate());
268 }
269
270 return isolate->factory()->undefined_value();
271 }
272
273
TryGetConstructorDelegate(Isolate * isolate,Handle<Object> object)274 MaybeHandle<Object> Execution::TryGetConstructorDelegate(
275 Isolate* isolate, Handle<Object> object) {
276 DCHECK(!object->IsJSFunction());
277
278 // If you return a function from here, it will be called when an
279 // attempt is made to call the given object as a constructor.
280
281 // If object is a function proxies, get its handler. Iterate if necessary.
282 Object* fun = *object;
283 while (fun->IsJSFunctionProxy()) {
284 fun = JSFunctionProxy::cast(fun)->call_trap();
285 }
286 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
287
288 // Objects created through the API can have an instance-call handler
289 // that should be used when calling the object as a function.
290 if (fun->IsHeapObject() &&
291 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
292 return Handle<JSFunction>(
293 isolate->native_context()->call_as_constructor_delegate());
294 }
295
296 // If the Object doesn't have an instance-call handler we should
297 // throw a non-callable exception.
298 THROW_NEW_ERROR(isolate, NewTypeError("called_non_callable",
299 i::HandleVector<i::Object>(&object, 1)),
300 Object);
301 }
302
303
EnableInterrupts()304 void StackGuard::EnableInterrupts() {
305 ExecutionAccess access(isolate_);
306 if (has_pending_interrupts(access)) {
307 set_interrupt_limits(access);
308 }
309 }
310
311
SetStackLimit(uintptr_t limit)312 void StackGuard::SetStackLimit(uintptr_t limit) {
313 ExecutionAccess access(isolate_);
314 // If the current limits are special (e.g. due to a pending interrupt) then
315 // leave them alone.
316 uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit);
317 if (thread_local_.jslimit_ == thread_local_.real_jslimit_) {
318 thread_local_.jslimit_ = jslimit;
319 }
320 if (thread_local_.climit_ == thread_local_.real_climit_) {
321 thread_local_.climit_ = limit;
322 }
323 thread_local_.real_climit_ = limit;
324 thread_local_.real_jslimit_ = jslimit;
325 }
326
327
DisableInterrupts()328 void StackGuard::DisableInterrupts() {
329 ExecutionAccess access(isolate_);
330 reset_limits(access);
331 }
332
333
PushPostponeInterruptsScope(PostponeInterruptsScope * scope)334 void StackGuard::PushPostponeInterruptsScope(PostponeInterruptsScope* scope) {
335 ExecutionAccess access(isolate_);
336 // Intercept already requested interrupts.
337 int intercepted = thread_local_.interrupt_flags_ & scope->intercept_mask_;
338 scope->intercepted_flags_ = intercepted;
339 thread_local_.interrupt_flags_ &= ~intercepted;
340 if (!has_pending_interrupts(access)) reset_limits(access);
341 // Add scope to the chain.
342 scope->prev_ = thread_local_.postpone_interrupts_;
343 thread_local_.postpone_interrupts_ = scope;
344 }
345
346
PopPostponeInterruptsScope()347 void StackGuard::PopPostponeInterruptsScope() {
348 ExecutionAccess access(isolate_);
349 PostponeInterruptsScope* top = thread_local_.postpone_interrupts_;
350 // Make intercepted interrupts active.
351 DCHECK((thread_local_.interrupt_flags_ & top->intercept_mask_) == 0);
352 thread_local_.interrupt_flags_ |= top->intercepted_flags_;
353 if (has_pending_interrupts(access)) set_interrupt_limits(access);
354 // Remove scope from chain.
355 thread_local_.postpone_interrupts_ = top->prev_;
356 }
357
358
CheckInterrupt(InterruptFlag flag)359 bool StackGuard::CheckInterrupt(InterruptFlag flag) {
360 ExecutionAccess access(isolate_);
361 return thread_local_.interrupt_flags_ & flag;
362 }
363
364
RequestInterrupt(InterruptFlag flag)365 void StackGuard::RequestInterrupt(InterruptFlag flag) {
366 ExecutionAccess access(isolate_);
367 // Check the chain of PostponeInterruptsScopes for interception.
368 if (thread_local_.postpone_interrupts_ &&
369 thread_local_.postpone_interrupts_->Intercept(flag)) {
370 return;
371 }
372
373 // Not intercepted. Set as active interrupt flag.
374 thread_local_.interrupt_flags_ |= flag;
375 set_interrupt_limits(access);
376 }
377
378
ClearInterrupt(InterruptFlag flag)379 void StackGuard::ClearInterrupt(InterruptFlag flag) {
380 ExecutionAccess access(isolate_);
381 // Clear the interrupt flag from the chain of PostponeInterruptsScopes.
382 for (PostponeInterruptsScope* current = thread_local_.postpone_interrupts_;
383 current != NULL;
384 current = current->prev_) {
385 current->intercepted_flags_ &= ~flag;
386 }
387
388 // Clear the interrupt flag from the active interrupt flags.
389 thread_local_.interrupt_flags_ &= ~flag;
390 if (!has_pending_interrupts(access)) reset_limits(access);
391 }
392
393
CheckAndClearInterrupt(InterruptFlag flag)394 bool StackGuard::CheckAndClearInterrupt(InterruptFlag flag) {
395 ExecutionAccess access(isolate_);
396 bool result = (thread_local_.interrupt_flags_ & flag);
397 thread_local_.interrupt_flags_ &= ~flag;
398 if (!has_pending_interrupts(access)) reset_limits(access);
399 return result;
400 }
401
402
ArchiveStackGuard(char * to)403 char* StackGuard::ArchiveStackGuard(char* to) {
404 ExecutionAccess access(isolate_);
405 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
406 ThreadLocal blank;
407
408 // Set the stack limits using the old thread_local_.
409 // TODO(isolates): This was the old semantics of constructing a ThreadLocal
410 // (as the ctor called SetStackLimits, which looked at the
411 // current thread_local_ from StackGuard)-- but is this
412 // really what was intended?
413 isolate_->heap()->SetStackLimits();
414 thread_local_ = blank;
415
416 return to + sizeof(ThreadLocal);
417 }
418
419
RestoreStackGuard(char * from)420 char* StackGuard::RestoreStackGuard(char* from) {
421 ExecutionAccess access(isolate_);
422 MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
423 isolate_->heap()->SetStackLimits();
424 return from + sizeof(ThreadLocal);
425 }
426
427
FreeThreadResources()428 void StackGuard::FreeThreadResources() {
429 Isolate::PerIsolateThreadData* per_thread =
430 isolate_->FindOrAllocatePerThreadDataForThisThread();
431 per_thread->set_stack_limit(thread_local_.real_climit_);
432 }
433
434
Clear()435 void StackGuard::ThreadLocal::Clear() {
436 real_jslimit_ = kIllegalLimit;
437 jslimit_ = kIllegalLimit;
438 real_climit_ = kIllegalLimit;
439 climit_ = kIllegalLimit;
440 postpone_interrupts_ = NULL;
441 interrupt_flags_ = 0;
442 }
443
444
Initialize(Isolate * isolate)445 bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) {
446 bool should_set_stack_limits = false;
447 if (real_climit_ == kIllegalLimit) {
448 const uintptr_t kLimitSize = FLAG_stack_size * KB;
449 DCHECK(GetCurrentStackPosition() > kLimitSize);
450 uintptr_t limit = GetCurrentStackPosition() - kLimitSize;
451 real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
452 jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
453 real_climit_ = limit;
454 climit_ = limit;
455 should_set_stack_limits = true;
456 }
457 postpone_interrupts_ = NULL;
458 interrupt_flags_ = 0;
459 return should_set_stack_limits;
460 }
461
462
ClearThread(const ExecutionAccess & lock)463 void StackGuard::ClearThread(const ExecutionAccess& lock) {
464 thread_local_.Clear();
465 isolate_->heap()->SetStackLimits();
466 }
467
468
InitThread(const ExecutionAccess & lock)469 void StackGuard::InitThread(const ExecutionAccess& lock) {
470 if (thread_local_.Initialize(isolate_)) isolate_->heap()->SetStackLimits();
471 Isolate::PerIsolateThreadData* per_thread =
472 isolate_->FindOrAllocatePerThreadDataForThisThread();
473 uintptr_t stored_limit = per_thread->stack_limit();
474 // You should hold the ExecutionAccess lock when you call this.
475 if (stored_limit != 0) {
476 SetStackLimit(stored_limit);
477 }
478 }
479
480
481 // --- C a l l s t o n a t i v e s ---
482
483 #define RETURN_NATIVE_CALL(name, args) \
484 do { \
485 Handle<Object> argv[] = args; \
486 return Call(isolate, \
487 isolate->name##_fun(), \
488 isolate->js_builtins_object(), \
489 arraysize(argv), argv); \
490 } while (false)
491
492
ToNumber(Isolate * isolate,Handle<Object> obj)493 MaybeHandle<Object> Execution::ToNumber(
494 Isolate* isolate, Handle<Object> obj) {
495 RETURN_NATIVE_CALL(to_number, { obj });
496 }
497
498
ToString(Isolate * isolate,Handle<Object> obj)499 MaybeHandle<Object> Execution::ToString(
500 Isolate* isolate, Handle<Object> obj) {
501 RETURN_NATIVE_CALL(to_string, { obj });
502 }
503
504
ToDetailString(Isolate * isolate,Handle<Object> obj)505 MaybeHandle<Object> Execution::ToDetailString(
506 Isolate* isolate, Handle<Object> obj) {
507 RETURN_NATIVE_CALL(to_detail_string, { obj });
508 }
509
510
ToObject(Isolate * isolate,Handle<Object> obj)511 MaybeHandle<Object> Execution::ToObject(
512 Isolate* isolate, Handle<Object> obj) {
513 if (obj->IsSpecObject()) return obj;
514 RETURN_NATIVE_CALL(to_object, { obj });
515 }
516
517
ToInteger(Isolate * isolate,Handle<Object> obj)518 MaybeHandle<Object> Execution::ToInteger(
519 Isolate* isolate, Handle<Object> obj) {
520 RETURN_NATIVE_CALL(to_integer, { obj });
521 }
522
523
ToUint32(Isolate * isolate,Handle<Object> obj)524 MaybeHandle<Object> Execution::ToUint32(
525 Isolate* isolate, Handle<Object> obj) {
526 RETURN_NATIVE_CALL(to_uint32, { obj });
527 }
528
529
ToInt32(Isolate * isolate,Handle<Object> obj)530 MaybeHandle<Object> Execution::ToInt32(
531 Isolate* isolate, Handle<Object> obj) {
532 RETURN_NATIVE_CALL(to_int32, { obj });
533 }
534
535
NewDate(Isolate * isolate,double time)536 MaybeHandle<Object> Execution::NewDate(Isolate* isolate, double time) {
537 Handle<Object> time_obj = isolate->factory()->NewNumber(time);
538 RETURN_NATIVE_CALL(create_date, { time_obj });
539 }
540
541
542 #undef RETURN_NATIVE_CALL
543
544
NewJSRegExp(Handle<String> pattern,Handle<String> flags)545 MaybeHandle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
546 Handle<String> flags) {
547 Isolate* isolate = pattern->GetIsolate();
548 Handle<JSFunction> function = Handle<JSFunction>(
549 isolate->native_context()->regexp_function());
550 Handle<Object> re_obj;
551 ASSIGN_RETURN_ON_EXCEPTION(
552 isolate, re_obj,
553 RegExpImpl::CreateRegExpLiteral(function, pattern, flags),
554 JSRegExp);
555 return Handle<JSRegExp>::cast(re_obj);
556 }
557
558
CharAt(Handle<String> string,uint32_t index)559 Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) {
560 Isolate* isolate = string->GetIsolate();
561 Factory* factory = isolate->factory();
562
563 int int_index = static_cast<int>(index);
564 if (int_index < 0 || int_index >= string->length()) {
565 return factory->undefined_value();
566 }
567
568 Handle<Object> char_at = Object::GetProperty(
569 isolate->js_builtins_object(),
570 factory->char_at_string()).ToHandleChecked();
571 if (!char_at->IsJSFunction()) {
572 return factory->undefined_value();
573 }
574
575 Handle<Object> index_object = factory->NewNumberFromInt(int_index);
576 Handle<Object> index_arg[] = { index_object };
577 Handle<Object> result;
578 if (!TryCall(Handle<JSFunction>::cast(char_at),
579 string,
580 arraysize(index_arg),
581 index_arg).ToHandle(&result)) {
582 return factory->undefined_value();
583 }
584 return result;
585 }
586
587
InstantiateFunction(Handle<FunctionTemplateInfo> data)588 MaybeHandle<JSFunction> Execution::InstantiateFunction(
589 Handle<FunctionTemplateInfo> data) {
590 Isolate* isolate = data->GetIsolate();
591 if (!data->do_not_cache()) {
592 // Fast case: see if the function has already been instantiated
593 int serial_number = Smi::cast(data->serial_number())->value();
594 Handle<JSObject> cache(isolate->native_context()->function_cache());
595 Handle<Object> elm =
596 Object::GetElement(isolate, cache, serial_number).ToHandleChecked();
597 if (elm->IsJSFunction()) return Handle<JSFunction>::cast(elm);
598 }
599 // The function has not yet been instantiated in this context; do it.
600 Handle<Object> args[] = { data };
601 Handle<Object> result;
602 ASSIGN_RETURN_ON_EXCEPTION(
603 isolate, result,
604 Call(isolate,
605 isolate->instantiate_fun(),
606 isolate->js_builtins_object(),
607 arraysize(args),
608 args),
609 JSFunction);
610 return Handle<JSFunction>::cast(result);
611 }
612
613
InstantiateObject(Handle<ObjectTemplateInfo> data)614 MaybeHandle<JSObject> Execution::InstantiateObject(
615 Handle<ObjectTemplateInfo> data) {
616 Isolate* isolate = data->GetIsolate();
617 Handle<Object> result;
618 if (data->property_list()->IsUndefined() &&
619 !data->constructor()->IsUndefined()) {
620 Handle<FunctionTemplateInfo> cons_template =
621 Handle<FunctionTemplateInfo>(
622 FunctionTemplateInfo::cast(data->constructor()));
623 Handle<JSFunction> cons;
624 ASSIGN_RETURN_ON_EXCEPTION(
625 isolate, cons, InstantiateFunction(cons_template), JSObject);
626 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, New(cons, 0, NULL), JSObject);
627 } else {
628 Handle<Object> args[] = { data };
629 ASSIGN_RETURN_ON_EXCEPTION(
630 isolate, result,
631 Call(isolate,
632 isolate->instantiate_fun(),
633 isolate->js_builtins_object(),
634 arraysize(args),
635 args),
636 JSObject);
637 }
638 return Handle<JSObject>::cast(result);
639 }
640
641
ConfigureInstance(Isolate * isolate,Handle<Object> instance,Handle<Object> instance_template)642 MaybeHandle<Object> Execution::ConfigureInstance(
643 Isolate* isolate,
644 Handle<Object> instance,
645 Handle<Object> instance_template) {
646 Handle<Object> args[] = { instance, instance_template };
647 return Execution::Call(isolate,
648 isolate->configure_instance_fun(),
649 isolate->js_builtins_object(),
650 arraysize(args),
651 args);
652 }
653
654
GetStackTraceLine(Handle<Object> recv,Handle<JSFunction> fun,Handle<Object> pos,Handle<Object> is_global)655 Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
656 Handle<JSFunction> fun,
657 Handle<Object> pos,
658 Handle<Object> is_global) {
659 Isolate* isolate = fun->GetIsolate();
660 Handle<Object> args[] = { recv, fun, pos, is_global };
661 MaybeHandle<Object> maybe_result =
662 TryCall(isolate->get_stack_trace_line_fun(),
663 isolate->js_builtins_object(),
664 arraysize(args),
665 args);
666 Handle<Object> result;
667 if (!maybe_result.ToHandle(&result) || !result->IsString()) {
668 return isolate->factory()->empty_string();
669 }
670
671 return Handle<String>::cast(result);
672 }
673
674
HandleInterrupts()675 Object* StackGuard::HandleInterrupts() {
676 if (CheckAndClearInterrupt(GC_REQUEST)) {
677 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags, "GC interrupt");
678 }
679
680 if (CheckDebugBreak() || CheckDebugCommand()) {
681 isolate_->debug()->HandleDebugBreak();
682 }
683
684 if (CheckAndClearInterrupt(TERMINATE_EXECUTION)) {
685 return isolate_->TerminateExecution();
686 }
687
688 if (CheckAndClearInterrupt(DEOPT_MARKED_ALLOCATION_SITES)) {
689 isolate_->heap()->DeoptMarkedAllocationSites();
690 }
691
692 if (CheckAndClearInterrupt(INSTALL_CODE)) {
693 DCHECK(isolate_->concurrent_recompilation_enabled());
694 isolate_->optimizing_compiler_thread()->InstallOptimizedFunctions();
695 }
696
697 if (CheckAndClearInterrupt(API_INTERRUPT)) {
698 // Callback must be invoked outside of ExecusionAccess lock.
699 isolate_->InvokeApiInterruptCallback();
700 }
701
702 isolate_->counters()->stack_interrupts()->Increment();
703 isolate_->counters()->runtime_profiler_ticks()->Increment();
704 isolate_->runtime_profiler()->OptimizeNow();
705
706 return isolate_->heap()->undefined_value();
707 }
708
709 } } // namespace v8::internal
710