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