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