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