ea1190efc1dc2e9ee167fd3f4bd3c15baa20cc84
[platform/upstream/v8.git] / src / execution.cc
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/messages.h"
12 #include "src/parser.h"
13 #include "src/prettyprinter.h"
14 #include "src/vm-state-inl.h"
15
16 namespace v8 {
17 namespace internal {
18
19 StackGuard::StackGuard()
20     : isolate_(NULL) {
21 }
22
23
24 void StackGuard::set_interrupt_limits(const ExecutionAccess& lock) {
25   DCHECK(isolate_ != NULL);
26   thread_local_.set_jslimit(kInterruptLimit);
27   thread_local_.set_climit(kInterruptLimit);
28   isolate_->heap()->SetStackLimits();
29 }
30
31
32 void StackGuard::reset_limits(const ExecutionAccess& lock) {
33   DCHECK(isolate_ != NULL);
34   thread_local_.set_jslimit(thread_local_.real_jslimit_);
35   thread_local_.set_climit(thread_local_.real_climit_);
36   isolate_->heap()->SetStackLimits();
37 }
38
39
40 static void PrintDeserializedCodeInfo(Handle<JSFunction> function) {
41   if (function->code() == function->shared()->code() &&
42       function->shared()->deserialized()) {
43     PrintF("[Running deserialized script");
44     Object* script = function->shared()->script();
45     if (script->IsScript()) {
46       Object* name = Script::cast(script)->name();
47       if (name->IsString()) {
48         PrintF(": %s", String::cast(name)->ToCString().get());
49       }
50     }
51     PrintF("]\n");
52   }
53 }
54
55
56 namespace {
57
58 MUST_USE_RESULT MaybeHandle<Object> Invoke(bool is_construct,
59                                            Handle<JSFunction> function,
60                                            Handle<Object> receiver, int argc,
61                                            Handle<Object> args[]) {
62   Isolate* const isolate = function->GetIsolate();
63
64   // Convert calls on global objects to be calls on the global
65   // receiver instead to avoid having a 'this' pointer which refers
66   // directly to a global object.
67   if (receiver->IsGlobalObject()) {
68     receiver =
69         handle(Handle<GlobalObject>::cast(receiver)->global_proxy(), isolate);
70   }
71
72   // api callbacks can be called directly.
73   if (!is_construct && function->shared()->IsApiFunction()) {
74     SaveContext save(isolate);
75     isolate->set_context(function->context());
76     // Do proper receiver conversion for non-strict mode api functions.
77     if (!receiver->IsJSReceiver() &&
78         is_sloppy(function->shared()->language_mode())) {
79       if (receiver->IsUndefined() || receiver->IsNull()) {
80         receiver = handle(function->global_proxy(), isolate);
81       } else {
82         ASSIGN_RETURN_ON_EXCEPTION(
83             isolate, receiver, Execution::ToObject(isolate, receiver), Object);
84       }
85     }
86     DCHECK(function->context()->global_object()->IsGlobalObject());
87     auto value = Builtins::InvokeApiFunction(function, receiver, argc, args);
88     bool has_exception = value.is_null();
89     DCHECK(has_exception == isolate->has_pending_exception());
90     if (has_exception) {
91       isolate->ReportPendingMessages();
92       return MaybeHandle<Object>();
93     } else {
94       isolate->clear_pending_message();
95     }
96     return value;
97   }
98
99   // Entering JavaScript.
100   VMState<JS> state(isolate);
101   CHECK(AllowJavascriptExecution::IsAllowed(isolate));
102   if (!ThrowOnJavascriptExecution::IsAllowed(isolate)) {
103     isolate->ThrowIllegalOperation();
104     isolate->ReportPendingMessages();
105     return MaybeHandle<Object>();
106   }
107
108   // Placeholder for return value.
109   Object* value = NULL;
110
111   typedef Object* (*JSEntryFunction)(byte* entry,
112                                      Object* function,
113                                      Object* receiver,
114                                      int argc,
115                                      Object*** args);
116
117   Handle<Code> code = is_construct
118       ? isolate->factory()->js_construct_entry_code()
119       : isolate->factory()->js_entry_code();
120
121   // Make sure that the global object of the context we're about to
122   // make the current one is indeed a global object.
123   DCHECK(function->context()->global_object()->IsGlobalObject());
124
125   {
126     // Save and restore context around invocation and block the
127     // allocation of handles without explicit handle scopes.
128     SaveContext save(isolate);
129     SealHandleScope shs(isolate);
130     JSEntryFunction stub_entry = FUNCTION_CAST<JSEntryFunction>(code->entry());
131
132     // Call the function through the right JS entry stub.
133     byte* ignored = nullptr;  // TODO(bmeurer): Remove this altogether.
134     JSFunction* func = *function;
135     Object* recv = *receiver;
136     Object*** argv = reinterpret_cast<Object***>(args);
137     if (FLAG_profile_deserialization) PrintDeserializedCodeInfo(function);
138     value = CALL_GENERATED_CODE(stub_entry, ignored, func, recv, argc, argv);
139   }
140
141 #ifdef VERIFY_HEAP
142   if (FLAG_verify_heap) {
143     value->ObjectVerify();
144   }
145 #endif
146
147   // Update the pending exception flag and return the value.
148   bool has_exception = value->IsException();
149   DCHECK(has_exception == isolate->has_pending_exception());
150   if (has_exception) {
151     isolate->ReportPendingMessages();
152     // Reset stepping state when script exits with uncaught exception.
153     if (isolate->debug()->is_active()) {
154       isolate->debug()->ClearStepping();
155     }
156     return MaybeHandle<Object>();
157   } else {
158     isolate->clear_pending_message();
159   }
160
161   return Handle<Object>(value, isolate);
162 }
163
164 }  // namespace
165
166
167 MaybeHandle<Object> Execution::Call(Isolate* isolate, Handle<Object> callable,
168                                     Handle<Object> receiver, int argc,
169                                     Handle<Object> argv[]) {
170   if (!callable->IsJSFunction()) {
171     ASSIGN_RETURN_ON_EXCEPTION(isolate, callable,
172                                GetFunctionDelegate(isolate, callable), Object);
173   }
174   Handle<JSFunction> func = Handle<JSFunction>::cast(callable);
175
176   return Invoke(false, func, receiver, argc, argv);
177 }
178
179
180 MaybeHandle<Object> Execution::New(Handle<JSFunction> func,
181                                    int argc,
182                                    Handle<Object> argv[]) {
183   return Invoke(true, func, handle(func->global_proxy()), argc, argv);
184 }
185
186
187 MaybeHandle<Object> Execution::TryCall(Handle<JSFunction> func,
188                                        Handle<Object> receiver, int argc,
189                                        Handle<Object> args[],
190                                        MaybeHandle<Object>* exception_out) {
191   bool is_termination = false;
192   Isolate* isolate = func->GetIsolate();
193   MaybeHandle<Object> maybe_result;
194   if (exception_out != NULL) *exception_out = MaybeHandle<Object>();
195   // Enter a try-block while executing the JavaScript code. To avoid
196   // duplicate error printing it must be non-verbose.  Also, to avoid
197   // creating message objects during stack overflow we shouldn't
198   // capture messages.
199   {
200     v8::TryCatch catcher(reinterpret_cast<v8::Isolate*>(isolate));
201     catcher.SetVerbose(false);
202     catcher.SetCaptureMessage(false);
203
204     maybe_result = Call(isolate, func, receiver, argc, args);
205
206     if (maybe_result.is_null()) {
207       DCHECK(catcher.HasCaught());
208       DCHECK(isolate->has_pending_exception());
209       DCHECK(isolate->external_caught_exception());
210       if (isolate->pending_exception() ==
211           isolate->heap()->termination_exception()) {
212         is_termination = true;
213       } else {
214         if (exception_out != NULL) {
215           *exception_out = v8::Utils::OpenHandle(*catcher.Exception());
216         }
217       }
218       isolate->OptionalRescheduleException(true);
219     }
220
221     DCHECK(!isolate->has_pending_exception());
222   }
223
224   // Re-request terminate execution interrupt to trigger later.
225   if (is_termination) isolate->stack_guard()->RequestTerminateExecution();
226
227   return maybe_result;
228 }
229
230
231 // static
232 MaybeHandle<JSFunction> Execution::GetFunctionDelegate(Isolate* isolate,
233                                                        Handle<Object> object) {
234   DCHECK(!object->IsJSFunction());
235   if (object->IsHeapObject()) {
236     DisallowHeapAllocation no_gc;
237
238     // If object is a function proxy, get its handler. Iterate if necessary.
239     Object* fun = *object;
240     while (fun->IsJSFunctionProxy()) {
241       fun = JSFunctionProxy::cast(fun)->call_trap();
242     }
243     if (fun->IsJSFunction()) {
244       return handle(JSFunction::cast(fun), isolate);
245     }
246
247     // We can also have exotic objects with [[Call]] internal methods.
248     if (fun->IsCallable()) {
249       return handle(isolate->native_context()->call_as_function_delegate(),
250                     isolate);
251     }
252   }
253
254   // If the Object doesn't have an instance-call handler we should
255   // throw a non-callable exception.
256   Handle<String> callsite = RenderCallSite(isolate, object);
257   THROW_NEW_ERROR(isolate,
258                   NewTypeError(MessageTemplate::kCalledNonCallable, callsite),
259                   JSFunction);
260 }
261
262
263 // static
264 MaybeHandle<JSFunction> Execution::GetConstructorDelegate(
265     Isolate* isolate, Handle<Object> object) {
266   // If you return a function from here, it will be called when an
267   // attempt is made to call the given object as a constructor.
268
269   DCHECK(!object->IsJSFunction());
270   if (object->IsHeapObject()) {
271     DisallowHeapAllocation no_gc;
272
273     // If object is a function proxies, get its handler. Iterate if necessary.
274     Object* fun = *object;
275     while (fun->IsJSFunctionProxy()) {
276       // TODO(bmeurer): This should work based on [[Construct]]; our proxies
277       // are screwed.
278       fun = JSFunctionProxy::cast(fun)->call_trap();
279     }
280     if (fun->IsJSFunction()) {
281       return handle(JSFunction::cast(fun), isolate);
282     }
283
284     // We can also have exotic objects with [[Construct]] internal methods.
285     // TODO(bmeurer): This should use IsConstructor() as dictacted by the spec.
286     if (fun->IsCallable()) {
287       return handle(isolate->native_context()->call_as_constructor_delegate(),
288                     isolate);
289     }
290   }
291
292   // If the Object doesn't have an instance-call handler we should
293   // throw a non-callable exception.
294   Handle<String> callsite = RenderCallSite(isolate, object);
295   THROW_NEW_ERROR(isolate,
296                   NewTypeError(MessageTemplate::kCalledNonCallable, callsite),
297                   JSFunction);
298 }
299
300
301 // static
302 Handle<String> Execution::RenderCallSite(Isolate* isolate,
303                                          Handle<Object> object) {
304   MessageLocation location;
305   if (isolate->ComputeLocation(&location)) {
306     Zone zone;
307     base::SmartPointer<ParseInfo> info(
308         location.function()->shared()->is_function()
309             ? new ParseInfo(&zone, location.function())
310             : new ParseInfo(&zone, location.script()));
311     if (Parser::ParseStatic(info.get())) {
312       CallPrinter printer(isolate, &zone);
313       const char* string = printer.Print(info->literal(), location.start_pos());
314       return isolate->factory()->NewStringFromAsciiChecked(string);
315     } else {
316       isolate->clear_pending_exception();
317     }
318   }
319   return Object::TypeOf(isolate, object);
320 }
321
322
323 void StackGuard::SetStackLimit(uintptr_t limit) {
324   ExecutionAccess access(isolate_);
325   // If the current limits are special (e.g. due to a pending interrupt) then
326   // leave them alone.
327   uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit);
328   if (thread_local_.jslimit() == thread_local_.real_jslimit_) {
329     thread_local_.set_jslimit(jslimit);
330   }
331   if (thread_local_.climit() == thread_local_.real_climit_) {
332     thread_local_.set_climit(limit);
333   }
334   thread_local_.real_climit_ = limit;
335   thread_local_.real_jslimit_ = jslimit;
336 }
337
338
339 void StackGuard::AdjustStackLimitForSimulator() {
340   ExecutionAccess access(isolate_);
341   uintptr_t climit = thread_local_.real_climit_;
342   // If the current limits are special (e.g. due to a pending interrupt) then
343   // leave them alone.
344   uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, climit);
345   if (thread_local_.jslimit() == thread_local_.real_jslimit_) {
346     thread_local_.set_jslimit(jslimit);
347     isolate_->heap()->SetStackLimits();
348   }
349 }
350
351
352 void StackGuard::EnableInterrupts() {
353   ExecutionAccess access(isolate_);
354   if (has_pending_interrupts(access)) {
355     set_interrupt_limits(access);
356   }
357 }
358
359
360 void StackGuard::DisableInterrupts() {
361   ExecutionAccess access(isolate_);
362   reset_limits(access);
363 }
364
365
366 void StackGuard::PushPostponeInterruptsScope(PostponeInterruptsScope* scope) {
367   ExecutionAccess access(isolate_);
368   // Intercept already requested interrupts.
369   int intercepted = thread_local_.interrupt_flags_ & scope->intercept_mask_;
370   scope->intercepted_flags_ = intercepted;
371   thread_local_.interrupt_flags_ &= ~intercepted;
372   if (!has_pending_interrupts(access)) reset_limits(access);
373   // Add scope to the chain.
374   scope->prev_ = thread_local_.postpone_interrupts_;
375   thread_local_.postpone_interrupts_ = scope;
376 }
377
378
379 void StackGuard::PopPostponeInterruptsScope() {
380   ExecutionAccess access(isolate_);
381   PostponeInterruptsScope* top = thread_local_.postpone_interrupts_;
382   // Make intercepted interrupts active.
383   DCHECK((thread_local_.interrupt_flags_ & top->intercept_mask_) == 0);
384   thread_local_.interrupt_flags_ |= top->intercepted_flags_;
385   if (has_pending_interrupts(access)) set_interrupt_limits(access);
386   // Remove scope from chain.
387   thread_local_.postpone_interrupts_ = top->prev_;
388 }
389
390
391 bool StackGuard::CheckInterrupt(InterruptFlag flag) {
392   ExecutionAccess access(isolate_);
393   return thread_local_.interrupt_flags_ & flag;
394 }
395
396
397 void StackGuard::RequestInterrupt(InterruptFlag flag) {
398   ExecutionAccess access(isolate_);
399   // Check the chain of PostponeInterruptsScopes for interception.
400   if (thread_local_.postpone_interrupts_ &&
401       thread_local_.postpone_interrupts_->Intercept(flag)) {
402     return;
403   }
404
405   // Not intercepted.  Set as active interrupt flag.
406   thread_local_.interrupt_flags_ |= flag;
407   set_interrupt_limits(access);
408
409   // If this isolate is waiting in a futex, notify it to wake up.
410   isolate_->futex_wait_list_node()->NotifyWake();
411 }
412
413
414 void StackGuard::ClearInterrupt(InterruptFlag flag) {
415   ExecutionAccess access(isolate_);
416   // Clear the interrupt flag from the chain of PostponeInterruptsScopes.
417   for (PostponeInterruptsScope* current = thread_local_.postpone_interrupts_;
418        current != NULL;
419        current = current->prev_) {
420     current->intercepted_flags_ &= ~flag;
421   }
422
423   // Clear the interrupt flag from the active interrupt flags.
424   thread_local_.interrupt_flags_ &= ~flag;
425   if (!has_pending_interrupts(access)) reset_limits(access);
426 }
427
428
429 bool StackGuard::CheckAndClearInterrupt(InterruptFlag flag) {
430   ExecutionAccess access(isolate_);
431   bool result = (thread_local_.interrupt_flags_ & flag);
432   thread_local_.interrupt_flags_ &= ~flag;
433   if (!has_pending_interrupts(access)) reset_limits(access);
434   return result;
435 }
436
437
438 char* StackGuard::ArchiveStackGuard(char* to) {
439   ExecutionAccess access(isolate_);
440   MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
441   ThreadLocal blank;
442
443   // Set the stack limits using the old thread_local_.
444   // TODO(isolates): This was the old semantics of constructing a ThreadLocal
445   //                 (as the ctor called SetStackLimits, which looked at the
446   //                 current thread_local_ from StackGuard)-- but is this
447   //                 really what was intended?
448   isolate_->heap()->SetStackLimits();
449   thread_local_ = blank;
450
451   return to + sizeof(ThreadLocal);
452 }
453
454
455 char* StackGuard::RestoreStackGuard(char* from) {
456   ExecutionAccess access(isolate_);
457   MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
458   isolate_->heap()->SetStackLimits();
459   return from + sizeof(ThreadLocal);
460 }
461
462
463 void StackGuard::FreeThreadResources() {
464   Isolate::PerIsolateThreadData* per_thread =
465       isolate_->FindOrAllocatePerThreadDataForThisThread();
466   per_thread->set_stack_limit(thread_local_.real_climit_);
467 }
468
469
470 void StackGuard::ThreadLocal::Clear() {
471   real_jslimit_ = kIllegalLimit;
472   set_jslimit(kIllegalLimit);
473   real_climit_ = kIllegalLimit;
474   set_climit(kIllegalLimit);
475   postpone_interrupts_ = NULL;
476   interrupt_flags_ = 0;
477 }
478
479
480 bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) {
481   bool should_set_stack_limits = false;
482   if (real_climit_ == kIllegalLimit) {
483     const uintptr_t kLimitSize = FLAG_stack_size * KB;
484     DCHECK(GetCurrentStackPosition() > kLimitSize);
485     uintptr_t limit = GetCurrentStackPosition() - kLimitSize;
486     real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
487     set_jslimit(SimulatorStack::JsLimitFromCLimit(isolate, limit));
488     real_climit_ = limit;
489     set_climit(limit);
490     should_set_stack_limits = true;
491   }
492   postpone_interrupts_ = NULL;
493   interrupt_flags_ = 0;
494   return should_set_stack_limits;
495 }
496
497
498 void StackGuard::ClearThread(const ExecutionAccess& lock) {
499   thread_local_.Clear();
500   isolate_->heap()->SetStackLimits();
501 }
502
503
504 void StackGuard::InitThread(const ExecutionAccess& lock) {
505   if (thread_local_.Initialize(isolate_)) isolate_->heap()->SetStackLimits();
506   Isolate::PerIsolateThreadData* per_thread =
507       isolate_->FindOrAllocatePerThreadDataForThisThread();
508   uintptr_t stored_limit = per_thread->stack_limit();
509   // You should hold the ExecutionAccess lock when you call this.
510   if (stored_limit != 0) {
511     SetStackLimit(stored_limit);
512   }
513 }
514
515
516 // --- C a l l s   t o   n a t i v e s ---
517
518 #define RETURN_NATIVE_CALL(name, args)                                         \
519   do {                                                                         \
520     Handle<Object> argv[] = args;                                              \
521     return Call(isolate, isolate->name##_fun(),                                \
522                 isolate->factory()->undefined_value(), arraysize(argv), argv); \
523   } while (false)
524
525
526 MaybeHandle<Object> Execution::ToDetailString(
527     Isolate* isolate, Handle<Object> obj) {
528   RETURN_NATIVE_CALL(to_detail_string, { obj });
529 }
530
531
532 MaybeHandle<Object> Execution::ToInteger(
533     Isolate* isolate, Handle<Object> obj) {
534   RETURN_NATIVE_CALL(to_integer, { obj });
535 }
536
537
538 MaybeHandle<Object> Execution::ToLength(
539     Isolate* isolate, Handle<Object> obj) {
540   RETURN_NATIVE_CALL(to_length, { obj });
541 }
542
543
544 MaybeHandle<Object> Execution::NewDate(Isolate* isolate, double time) {
545   Handle<Object> time_obj = isolate->factory()->NewNumber(time);
546   RETURN_NATIVE_CALL(create_date, { time_obj });
547 }
548
549
550 #undef RETURN_NATIVE_CALL
551
552
553 MaybeHandle<Object> Execution::ToInt32(Isolate* isolate, Handle<Object> obj) {
554   ASSIGN_RETURN_ON_EXCEPTION(isolate, obj, Object::ToNumber(obj), Object);
555   return isolate->factory()->NewNumberFromInt(DoubleToInt32(obj->Number()));
556 }
557
558
559 MaybeHandle<Object> Execution::ToObject(Isolate* isolate, Handle<Object> obj) {
560   Handle<JSReceiver> receiver;
561   if (JSReceiver::ToObject(isolate, obj).ToHandle(&receiver)) {
562     return receiver;
563   }
564   THROW_NEW_ERROR(
565       isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject), Object);
566 }
567
568
569 MaybeHandle<Object> Execution::ToUint32(Isolate* isolate, Handle<Object> obj) {
570   ASSIGN_RETURN_ON_EXCEPTION(isolate, obj, Object::ToNumber(obj), Object);
571   return isolate->factory()->NewNumberFromUint(DoubleToUint32(obj->Number()));
572 }
573
574
575 MaybeHandle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
576                                              Handle<String> flags) {
577   Isolate* isolate = pattern->GetIsolate();
578   Handle<JSFunction> function = Handle<JSFunction>(
579       isolate->native_context()->regexp_function());
580   Handle<Object> re_obj;
581   ASSIGN_RETURN_ON_EXCEPTION(
582       isolate, re_obj,
583       RegExpImpl::CreateRegExpLiteral(function, pattern, flags),
584       JSRegExp);
585   return Handle<JSRegExp>::cast(re_obj);
586 }
587
588
589 Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
590                                             Handle<JSFunction> fun,
591                                             Handle<Object> pos,
592                                             Handle<Object> is_global) {
593   Isolate* isolate = fun->GetIsolate();
594   Handle<Object> args[] = { recv, fun, pos, is_global };
595   MaybeHandle<Object> maybe_result =
596       TryCall(isolate->get_stack_trace_line_fun(),
597               isolate->factory()->undefined_value(), arraysize(args), args);
598   Handle<Object> result;
599   if (!maybe_result.ToHandle(&result) || !result->IsString()) {
600     return isolate->factory()->empty_string();
601   }
602
603   return Handle<String>::cast(result);
604 }
605
606
607 void StackGuard::HandleGCInterrupt() {
608   if (CheckAndClearInterrupt(GC_REQUEST)) {
609     isolate_->heap()->HandleGCRequest();
610   }
611 }
612
613
614 Object* StackGuard::HandleInterrupts() {
615   if (CheckAndClearInterrupt(GC_REQUEST)) {
616     isolate_->heap()->HandleGCRequest();
617   }
618
619   if (CheckDebugBreak() || CheckDebugCommand()) {
620     isolate_->debug()->HandleDebugBreak();
621   }
622
623   if (CheckAndClearInterrupt(TERMINATE_EXECUTION)) {
624     return isolate_->TerminateExecution();
625   }
626
627   if (CheckAndClearInterrupt(DEOPT_MARKED_ALLOCATION_SITES)) {
628     isolate_->heap()->DeoptMarkedAllocationSites();
629   }
630
631   if (CheckAndClearInterrupt(INSTALL_CODE)) {
632     DCHECK(isolate_->concurrent_recompilation_enabled());
633     isolate_->optimizing_compile_dispatcher()->InstallOptimizedFunctions();
634   }
635
636   if (CheckAndClearInterrupt(API_INTERRUPT)) {
637     // Callbacks must be invoked outside of ExecusionAccess lock.
638     isolate_->InvokeApiInterruptCallbacks();
639   }
640
641   isolate_->counters()->stack_interrupts()->Increment();
642   isolate_->counters()->runtime_profiler_ticks()->Increment();
643   isolate_->runtime_profiler()->OptimizeNow();
644
645   return isolate_->heap()->undefined_value();
646 }
647
648 }  // namespace internal
649 }  // namespace v8