runtime-compiler.cc revision 958fae7ec3f466955f8e5b50fa5b8d38b9e91675
1958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Copyright 2014 the V8 project authors. All rights reserved.
2958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Use of this source code is governed by a BSD-style license that can be
3958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// found in the LICENSE file.
4958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
5958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/v8.h"
6958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
7958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/arguments.h"
8958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/compiler.h"
9958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/deoptimizer.h"
10958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/frames.h"
11958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/full-codegen.h"
12958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/isolate-inl.h"
13958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/runtime/runtime-utils.h"
14958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/v8threads.h"
15958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/vm-state-inl.h"
16958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
17958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace v8 {
18958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace internal {
19958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
20958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRUNTIME_FUNCTION(Runtime_CompileLazy) {
21958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  HandleScope scope(isolate);
22958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(args.length() == 1);
23958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
24958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#ifdef DEBUG
25958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (FLAG_trace_lazy && !function->shared()->is_compiled()) {
26958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    PrintF("[unoptimized: ");
27958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    function->PrintName();
28958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    PrintF("]\n");
29958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
30958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif
31958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
32958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Compile the target function.
33958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(function->shared()->allows_lazy_compilation());
34958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
35958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<Code> code;
36958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, code,
37958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     Compiler::GetLazyCode(function));
38958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(code->kind() == Code::FUNCTION ||
39958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier         code->kind() == Code::OPTIMIZED_FUNCTION);
40958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  function->ReplaceCode(*code);
41958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return *code;
42958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
43958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
44958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
45958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRUNTIME_FUNCTION(Runtime_CompileOptimized) {
46958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  HandleScope scope(isolate);
47958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(args.length() == 2);
48958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
49958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CONVERT_BOOLEAN_ARG_CHECKED(concurrent, 1);
50958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(isolate->use_crankshaft());
51958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
52958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<Code> unoptimized(function->shared()->code());
53958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (function->shared()->optimization_disabled() ||
54958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      isolate->DebuggerHasBreakPoints()) {
55958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // If the function is not optimizable or debugger is active continue
56958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // using the code from the full compiler.
57958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (FLAG_trace_opt) {
58958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      PrintF("[failed to optimize ");
59958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      function->PrintName();
60958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      PrintF(": is code optimizable: %s, is debugger enabled: %s]\n",
61958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             function->shared()->optimization_disabled() ? "F" : "T",
62958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             isolate->DebuggerHasBreakPoints() ? "T" : "F");
63958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
64958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    function->ReplaceCode(*unoptimized);
65958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return function->code();
66958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
67958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
68958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Compiler::ConcurrencyMode mode =
69958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      concurrent ? Compiler::CONCURRENT : Compiler::NOT_CONCURRENT;
70958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<Code> code;
71958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (Compiler::GetOptimizedCode(function, unoptimized, mode).ToHandle(&code)) {
72958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    function->ReplaceCode(*code);
73958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
74958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    function->ReplaceCode(function->shared()->code());
75958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
76958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
77958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(function->code()->kind() == Code::FUNCTION ||
78958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier         function->code()->kind() == Code::OPTIMIZED_FUNCTION ||
79958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier         function->IsInOptimizationQueue());
80958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return function->code();
81958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
82958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
83958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
84958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRUNTIME_FUNCTION(Runtime_NotifyStubFailure) {
85958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  HandleScope scope(isolate);
86958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(args.length() == 0);
87958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
88958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(AllowHeapAllocation::IsAllowed());
89958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  delete deoptimizer;
90958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return isolate->heap()->undefined_value();
91958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
92958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
93958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
94958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierclass ActivationsFinder : public ThreadVisitor {
95958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier public:
96958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Code* code_;
97958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool has_code_activations_;
98958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
99958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  explicit ActivationsFinder(Code* code)
100958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      : code_(code), has_code_activations_(false) {}
101958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
102958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    JavaScriptFrameIterator it(isolate, top);
104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    VisitFrames(&it);
105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void VisitFrames(JavaScriptFrameIterator* it) {
108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    for (; !it->done(); it->Advance()) {
109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      JavaScriptFrame* frame = it->frame();
110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (code_->contains(frame->pc())) has_code_activations_ = true;
111958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier};
114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRUNTIME_FUNCTION(Runtime_NotifyDeoptimized) {
117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  HandleScope scope(isolate);
118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(args.length() == 1);
119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CONVERT_SMI_ARG_CHECKED(type_arg, 0);
120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Deoptimizer::BailoutType type =
121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      static_cast<Deoptimizer::BailoutType>(type_arg);
122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(AllowHeapAllocation::IsAllowed());
124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<JSFunction> function = deoptimizer->function();
126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<Code> optimized_code = deoptimizer->compiled_code();
127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(optimized_code->kind() == Code::OPTIMIZED_FUNCTION);
129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(type == deoptimizer->bailout_type());
130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Make sure to materialize objects before causing any allocation.
132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  JavaScriptFrameIterator it(isolate);
133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  deoptimizer->MaterializeHeapObjects(&it);
134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  delete deoptimizer;
135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  JavaScriptFrame* frame = it.frame();
137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  RUNTIME_ASSERT(frame->function()->IsJSFunction());
138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(frame->function() == *function);
139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Avoid doing too much work when running with --always-opt and keep
141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // the optimized code around.
142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (FLAG_always_opt || type == Deoptimizer::LAZY) {
143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return isolate->heap()->undefined_value();
144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Search for other activations of the same function and code.
147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ActivationsFinder activations_finder(*optimized_code);
148958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  activations_finder.VisitFrames(&it);
149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  isolate->thread_manager()->IterateArchivedThreads(&activations_finder);
150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (!activations_finder.has_code_activations_) {
152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (function->code() == *optimized_code) {
153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (FLAG_trace_deopt) {
154958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        PrintF("[removing optimized code for: ");
155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        function->PrintName();
156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        PrintF("]\n");
157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      function->ReplaceCode(function->shared()->code());
159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // Evict optimized code for this function from the cache so that it
160958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // doesn't get used for new closures.
161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      function->shared()->EvictFromOptimizedCodeMap(*optimized_code,
162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                    "notify deoptimized");
163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
165958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // TODO(titzer): we should probably do DeoptimizeCodeList(code)
166958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // unconditionally if the code is not already marked for deoptimization.
167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // If there is an index by shared function info, all the better.
168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Deoptimizer::DeoptimizeFunction(*function);
169958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
170958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return isolate->heap()->undefined_value();
172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
173958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
174958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
175958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic bool IsSuitableForOnStackReplacement(Isolate* isolate,
176958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                            Handle<JSFunction> function,
177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                            Handle<Code> current_code) {
178958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Keep track of whether we've succeeded in optimizing.
179958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (!current_code->optimizable()) return false;
180958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // If we are trying to do OSR when there are already optimized
181958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // activations of the function, it means (a) the function is directly or
182958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // indirectly recursive and (b) an optimized invocation has been
183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // deoptimized so that we are currently in an unoptimized activation.
184958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check for optimized activations of this function.
185958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
186958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    JavaScriptFrame* frame = it.frame();
187958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (frame->is_optimized() && frame->function() == *function) return false;
188958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
189958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
190958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return true;
191958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
192958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRUNTIME_FUNCTION(Runtime_CompileForOnStackReplacement) {
195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  HandleScope scope(isolate);
196958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(args.length() == 1);
197958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
198958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<Code> caller_code(function->shared()->code());
199958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
200958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // We're not prepared to handle a function with arguments object.
201958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!function->shared()->uses_arguments());
202958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
203958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  RUNTIME_ASSERT(FLAG_use_osr);
204958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
205958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Passing the PC in the javascript frame from the caller directly is
206958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // not GC safe, so we walk the stack to get it.
207958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  JavaScriptFrameIterator it(isolate);
208958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  JavaScriptFrame* frame = it.frame();
209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (!caller_code->contains(frame->pc())) {
210958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Code on the stack may not be the code object referenced by the shared
211958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // function info.  It may have been replaced to include deoptimization data.
212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    caller_code = Handle<Code>(frame->LookupCode());
213958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
215958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  uint32_t pc_offset =
216958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      static_cast<uint32_t>(frame->pc() - caller_code->instruction_start());
217958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
218958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#ifdef DEBUG
219958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK_EQ(frame->function(), *function);
220958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK_EQ(frame->LookupCode(), *caller_code);
221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(caller_code->contains(frame->pc()));
222958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#endif  // DEBUG
223958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
224958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
225958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  BailoutId ast_id = caller_code->TranslatePcOffsetToAstId(pc_offset);
226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(!ast_id.IsNone());
227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
228958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Compiler::ConcurrencyMode mode =
229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      isolate->concurrent_osr_enabled() &&
230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              (function->shared()->ast_node_count() > 512)
231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          ? Compiler::CONCURRENT
232958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          : Compiler::NOT_CONCURRENT;
233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<Code> result = Handle<Code>::null();
234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  OptimizedCompileJob* job = NULL;
236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (mode == Compiler::CONCURRENT) {
237958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Gate the OSR entry with a stack check.
238958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    BackEdgeTable::AddStackCheck(caller_code, pc_offset);
239958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Poll already queued compilation jobs.
240958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    OptimizingCompilerThread* thread = isolate->optimizing_compiler_thread();
241958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (thread->IsQueuedForOSR(function, ast_id)) {
242958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (FLAG_trace_osr) {
243958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        PrintF("[OSR - Still waiting for queued: ");
244958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        function->PrintName();
245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        PrintF(" at AST id %d]\n", ast_id.ToInt());
246958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return NULL;
248958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
250958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    job = thread->FindReadyOSRCandidate(function, ast_id);
251958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
252958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
253958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (job != NULL) {
254958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (FLAG_trace_osr) {
255958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      PrintF("[OSR - Found ready: ");
256958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      function->PrintName();
257958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      PrintF(" at AST id %d]\n", ast_id.ToInt());
258958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
259958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    result = Compiler::GetConcurrentlyOptimizedCode(job);
260958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else if (IsSuitableForOnStackReplacement(isolate, function, caller_code)) {
261958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (FLAG_trace_osr) {
262958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      PrintF("[OSR - Compiling: ");
263958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      function->PrintName();
264958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      PrintF(" at AST id %d]\n", ast_id.ToInt());
265958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
266958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    MaybeHandle<Code> maybe_result =
267958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Compiler::GetOptimizedCode(function, caller_code, mode, ast_id);
268958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (maybe_result.ToHandle(&result) &&
269958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        result.is_identical_to(isolate->builtins()->InOptimizationQueue())) {
270958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // Optimization is queued.  Return to check later.
271958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return NULL;
272958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
273958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
274958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
275958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Revert the patched back edge table, regardless of whether OSR succeeds.
276958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  BackEdgeTable::Revert(isolate, *caller_code);
277958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
278958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check whether we ended up with usable optimized code.
279958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (!result.is_null() && result->kind() == Code::OPTIMIZED_FUNCTION) {
280958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DeoptimizationInputData* data =
281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        DeoptimizationInputData::cast(result->deoptimization_data());
282958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (data->OsrPcOffset()->value() >= 0) {
284958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      DCHECK(BailoutId(data->OsrAstId()->value()) == ast_id);
285958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (FLAG_trace_osr) {
286958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        PrintF("[OSR - Entry at AST id %d, offset %d in optimized code]\n",
287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier               ast_id.ToInt(), data->OsrPcOffset()->value());
288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
289958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // TODO(titzer): this is a massive hack to make the deopt counts
290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // match. Fix heuristics for reenabling optimizations!
291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      function->shared()->increment_deopt_count();
292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // TODO(titzer): Do not install code into the function.
294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      function->ReplaceCode(*result);
295958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return *result;
296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
297958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Failed.
300958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (FLAG_trace_osr) {
301958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    PrintF("[OSR - Failed: ");
302958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    function->PrintName();
303958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    PrintF(" at AST id %d]\n", ast_id.ToInt());
304958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
305958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
306958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (!function->IsOptimized()) {
307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    function->ReplaceCode(function->shared()->code());
308958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
309958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return NULL;
310958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
311958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
312958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
313958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRUNTIME_FUNCTION(Runtime_TryInstallOptimizedCode) {
314958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  HandleScope scope(isolate);
315958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(args.length() == 1);
316958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
317958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
318958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // First check if this is a real stack overflow.
319958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  StackLimitCheck check(isolate);
320958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (check.JsHasOverflowed()) {
321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    SealHandleScope shs(isolate);
322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return isolate->StackOverflow();
323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return (function->IsOptimized()) ? function->code()
327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                   : function->shared()->code();
328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierbool CodeGenerationFromStringsAllowed(Isolate* isolate,
332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                      Handle<Context> context) {
333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(context->allow_code_gen_from_strings()->IsFalse());
334958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check with callback if set.
335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  AllowCodeGenerationFromStringsCallback callback =
336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      isolate->allow_code_gen_callback();
337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (callback == NULL) {
338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // No callback set and code generation disallowed.
339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return false;
340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
341958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Callback set. Let it decide if code generation is allowed.
342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    VMState<EXTERNAL> state(isolate);
343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return callback(v8::Utils::ToLocal(context));
344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
345958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
346958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
347958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
348958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRUNTIME_FUNCTION(Runtime_CompileString) {
349958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  HandleScope scope(isolate);
350958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(args.length() == 3);
351958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
352958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CONVERT_BOOLEAN_ARG_CHECKED(function_literal_only, 1);
353958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CONVERT_SMI_ARG_CHECKED(source_offset, 2);
354958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
355958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Extract native context.
356958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<Context> context(isolate->native_context());
357958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
358958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check if native context allows code generation from
359958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // strings. Throw an exception if it doesn't.
360958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (context->allow_code_gen_from_strings()->IsFalse() &&
361958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      !CodeGenerationFromStringsAllowed(isolate, context)) {
362958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Handle<Object> error_message =
363958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        context->ErrorMessageForCodeGenerationFromStrings();
364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    THROW_NEW_ERROR_RETURN_FAILURE(
365958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        isolate, NewEvalError("code_gen_from_strings",
366958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                              HandleVector<Object>(&error_message, 1)));
367958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
368958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
369958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Compile source string in the native context.
370958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ParseRestriction restriction = function_literal_only
371958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     ? ONLY_SINGLE_FUNCTION_LITERAL
372958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                     : NO_PARSE_RESTRICTION;
373958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<SharedFunctionInfo> outer_info(context->closure()->shared(), isolate);
374958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<JSFunction> fun;
375958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
376958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      isolate, fun,
377958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Compiler::GetFunctionFromEval(source, outer_info, context, SLOPPY,
378958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                    restriction, RelocInfo::kNoPosition));
379958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (function_literal_only) {
380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // The actual body is wrapped, which shifts line numbers.
381958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Handle<Script> script(Script::cast(fun->shared()->script()), isolate);
382958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (script->line_offset() == 0) {
383958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      int line_num = Script::GetLineNumber(script, source_offset);
384958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      script->set_line_offset(Smi::FromInt(-line_num));
385958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
386958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
387958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return *fun;
388958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
389958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
390958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
391958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic ObjectPair CompileGlobalEval(Isolate* isolate, Handle<String> source,
392958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                    Handle<SharedFunctionInfo> outer_info,
393958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                    Handle<Object> receiver,
394958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                    StrictMode strict_mode,
395958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                    int scope_position) {
396958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<Context> context = Handle<Context>(isolate->context());
397958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<Context> native_context = Handle<Context>(context->native_context());
398958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
399958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Check if native context allows code generation from
400958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // strings. Throw an exception if it doesn't.
401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (native_context->allow_code_gen_from_strings()->IsFalse() &&
402958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      !CodeGenerationFromStringsAllowed(isolate, native_context)) {
403958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Handle<Object> error_message =
404958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        native_context->ErrorMessageForCodeGenerationFromStrings();
405958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Handle<Object> error;
406958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    MaybeHandle<Object> maybe_error = isolate->factory()->NewEvalError(
407958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        "code_gen_from_strings", HandleVector<Object>(&error_message, 1));
408958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (maybe_error.ToHandle(&error)) isolate->Throw(*error);
409958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return MakePair(isolate->heap()->exception(), NULL);
410958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
411958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Deal with a normal eval call with a string argument. Compile it
413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // and return the compiled function bound in the local context.
414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static const ParseRestriction restriction = NO_PARSE_RESTRICTION;
415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<JSFunction> compiled;
416958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
417958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      isolate, compiled,
418958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Compiler::GetFunctionFromEval(source, outer_info, context, strict_mode,
419958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                    restriction, scope_position),
420958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      MakePair(isolate->heap()->exception(), NULL));
421958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return MakePair(*compiled, *receiver);
422958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
423958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
424958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
425958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRUNTIME_FUNCTION_RETURN_PAIR(Runtime_ResolvePossiblyDirectEval) {
426958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  HandleScope scope(isolate);
427958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(args.length() == 6);
428958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
429958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<Object> callee = args.at<Object>(0);
430958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
431958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // If "eval" didn't refer to the original GlobalEval, it's not a
432958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // direct call to eval.
433958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // (And even if it is, but the first argument isn't a string, just let
434958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // execution default to an indirect call to eval, which will also return
435958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // the first argument without doing anything).
436958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (*callee != isolate->native_context()->global_eval_fun() ||
437958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      !args[1]->IsString()) {
438958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return MakePair(*callee, isolate->heap()->undefined_value());
439958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
440958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
441958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(args[4]->IsSmi());
442958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(args.smi_at(4) == SLOPPY || args.smi_at(4) == STRICT);
443958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  StrictMode strict_mode = static_cast<StrictMode>(args.smi_at(4));
444958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(args[5]->IsSmi());
445958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<SharedFunctionInfo> outer_info(args.at<JSFunction>(2)->shared(),
446958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                        isolate);
447958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return CompileGlobalEval(isolate, args.at<String>(1), outer_info,
448958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                           args.at<Object>(3), strict_mode, args.smi_at(5));
449958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
450958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
451958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}  // namespace v8::internal
452