OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/execution.h" | 5 #include "src/execution.h" |
6 | 6 |
7 #include "src/bootstrapper.h" | 7 #include "src/bootstrapper.h" |
8 #include "src/codegen.h" | 8 #include "src/codegen.h" |
9 #include "src/deoptimizer.h" | 9 #include "src/deoptimizer.h" |
10 #include "src/isolate-inl.h" | 10 #include "src/isolate-inl.h" |
11 #include "src/messages.h" | 11 #include "src/messages.h" |
12 #include "src/parser.h" | |
13 #include "src/prettyprinter.h" | |
14 #include "src/vm-state-inl.h" | 12 #include "src/vm-state-inl.h" |
15 | 13 |
16 namespace v8 { | 14 namespace v8 { |
17 namespace internal { | 15 namespace internal { |
18 | 16 |
19 StackGuard::StackGuard() | 17 StackGuard::StackGuard() |
20 : isolate_(NULL) { | 18 : isolate_(NULL) { |
21 } | 19 } |
22 | 20 |
23 | 21 |
(...skipping 24 matching lines...) Expand all Loading... |
48 PrintF(": %s", String::cast(name)->ToCString().get()); | 46 PrintF(": %s", String::cast(name)->ToCString().get()); |
49 } | 47 } |
50 } | 48 } |
51 PrintF("]\n"); | 49 PrintF("]\n"); |
52 } | 50 } |
53 } | 51 } |
54 | 52 |
55 | 53 |
56 namespace { | 54 namespace { |
57 | 55 |
58 MUST_USE_RESULT MaybeHandle<Object> Invoke(bool is_construct, | 56 MUST_USE_RESULT MaybeHandle<Object> Invoke(Isolate* isolate, bool is_construct, |
59 Handle<JSFunction> function, | 57 Handle<Object> target, |
60 Handle<Object> receiver, int argc, | 58 Handle<Object> receiver, int argc, |
61 Handle<Object> args[], | 59 Handle<Object> args[], |
62 Handle<Object> new_target) { | 60 Handle<Object> new_target) { |
63 Isolate* const isolate = function->GetIsolate(); | 61 DCHECK(!receiver->IsGlobalObject()); |
64 | |
65 // Convert calls on global objects to be calls on the global | |
66 // receiver instead to avoid having a 'this' pointer which refers | |
67 // directly to a global object. | |
68 if (receiver->IsGlobalObject()) { | |
69 receiver = | |
70 handle(Handle<GlobalObject>::cast(receiver)->global_proxy(), isolate); | |
71 } | |
72 | |
73 // api callbacks can be called directly. | |
74 if (!is_construct && function->shared()->IsApiFunction()) { | |
75 SaveContext save(isolate); | |
76 isolate->set_context(function->context()); | |
77 // Do proper receiver conversion for non-strict mode api functions. | |
78 if (!receiver->IsJSReceiver() && | |
79 is_sloppy(function->shared()->language_mode())) { | |
80 if (receiver->IsUndefined() || receiver->IsNull()) { | |
81 receiver = handle(function->global_proxy(), isolate); | |
82 } else { | |
83 ASSIGN_RETURN_ON_EXCEPTION( | |
84 isolate, receiver, Execution::ToObject(isolate, receiver), Object); | |
85 } | |
86 } | |
87 DCHECK(function->context()->global_object()->IsGlobalObject()); | |
88 auto value = Builtins::InvokeApiFunction(function, receiver, argc, args); | |
89 bool has_exception = value.is_null(); | |
90 DCHECK(has_exception == isolate->has_pending_exception()); | |
91 if (has_exception) { | |
92 isolate->ReportPendingMessages(); | |
93 return MaybeHandle<Object>(); | |
94 } else { | |
95 isolate->clear_pending_message(); | |
96 } | |
97 return value; | |
98 } | |
99 | 62 |
100 // Entering JavaScript. | 63 // Entering JavaScript. |
101 VMState<JS> state(isolate); | 64 VMState<JS> state(isolate); |
102 CHECK(AllowJavascriptExecution::IsAllowed(isolate)); | 65 CHECK(AllowJavascriptExecution::IsAllowed(isolate)); |
103 if (!ThrowOnJavascriptExecution::IsAllowed(isolate)) { | 66 if (!ThrowOnJavascriptExecution::IsAllowed(isolate)) { |
104 isolate->ThrowIllegalOperation(); | 67 isolate->ThrowIllegalOperation(); |
105 isolate->ReportPendingMessages(); | 68 isolate->ReportPendingMessages(); |
106 return MaybeHandle<Object>(); | 69 return MaybeHandle<Object>(); |
107 } | 70 } |
108 | 71 |
109 // Placeholder for return value. | 72 // Placeholder for return value. |
110 Object* value = NULL; | 73 Object* value = NULL; |
111 | 74 |
112 typedef Object* (*JSEntryFunction)(Object* new_target, Object* function, | 75 typedef Object* (*JSEntryFunction)(Object* new_target, Object* target, |
113 Object* receiver, int argc, | 76 Object* receiver, int argc, |
114 Object*** args); | 77 Object*** args); |
115 | 78 |
116 Handle<Code> code = is_construct | 79 Handle<Code> code = is_construct |
117 ? isolate->factory()->js_construct_entry_code() | 80 ? isolate->factory()->js_construct_entry_code() |
118 : isolate->factory()->js_entry_code(); | 81 : isolate->factory()->js_entry_code(); |
119 | 82 |
120 // Make sure that the global object of the context we're about to | |
121 // make the current one is indeed a global object. | |
122 DCHECK(function->context()->global_object()->IsGlobalObject()); | |
123 | |
124 { | 83 { |
125 // Save and restore context around invocation and block the | 84 // Save and restore context around invocation and block the |
126 // allocation of handles without explicit handle scopes. | 85 // allocation of handles without explicit handle scopes. |
127 SaveContext save(isolate); | 86 SaveContext save(isolate); |
128 SealHandleScope shs(isolate); | 87 SealHandleScope shs(isolate); |
129 JSEntryFunction stub_entry = FUNCTION_CAST<JSEntryFunction>(code->entry()); | 88 JSEntryFunction stub_entry = FUNCTION_CAST<JSEntryFunction>(code->entry()); |
130 | 89 |
131 // Call the function through the right JS entry stub. | 90 // Call the function through the right JS entry stub. |
132 Object* orig_func = *new_target; | 91 Object* orig_func = *new_target; |
133 JSFunction* func = *function; | 92 Object* func = *target; |
134 Object* recv = *receiver; | 93 Object* recv = *receiver; |
135 Object*** argv = reinterpret_cast<Object***>(args); | 94 Object*** argv = reinterpret_cast<Object***>(args); |
136 if (FLAG_profile_deserialization) PrintDeserializedCodeInfo(function); | 95 if (FLAG_profile_deserialization && target->IsJSFunction()) { |
| 96 PrintDeserializedCodeInfo(Handle<JSFunction>::cast(target)); |
| 97 } |
137 value = CALL_GENERATED_CODE(stub_entry, orig_func, func, recv, argc, argv); | 98 value = CALL_GENERATED_CODE(stub_entry, orig_func, func, recv, argc, argv); |
138 } | 99 } |
139 | 100 |
140 #ifdef VERIFY_HEAP | 101 #ifdef VERIFY_HEAP |
141 if (FLAG_verify_heap) { | 102 if (FLAG_verify_heap) { |
142 value->ObjectVerify(); | 103 value->ObjectVerify(); |
143 } | 104 } |
144 #endif | 105 #endif |
145 | 106 |
146 // Update the pending exception flag and return the value. | 107 // Update the pending exception flag and return the value. |
147 bool has_exception = value->IsException(); | 108 bool has_exception = value->IsException(); |
148 DCHECK(has_exception == isolate->has_pending_exception()); | 109 DCHECK(has_exception == isolate->has_pending_exception()); |
149 if (has_exception) { | 110 if (has_exception) { |
150 isolate->ReportPendingMessages(); | 111 isolate->ReportPendingMessages(); |
151 // Reset stepping state when script exits with uncaught exception. | 112 // Reset stepping state when script exits with uncaught exception. |
152 if (isolate->debug()->is_active()) { | 113 if (isolate->debug()->is_active()) { |
153 isolate->debug()->ClearStepping(); | 114 isolate->debug()->ClearStepping(); |
154 } | 115 } |
155 return MaybeHandle<Object>(); | 116 return MaybeHandle<Object>(); |
156 } else { | 117 } else { |
157 isolate->clear_pending_message(); | 118 isolate->clear_pending_message(); |
158 } | 119 } |
159 | 120 |
160 return Handle<Object>(value, isolate); | 121 return Handle<Object>(value, isolate); |
161 } | 122 } |
162 | 123 |
163 } // namespace | 124 } // namespace |
164 | 125 |
165 | 126 |
| 127 // static |
166 MaybeHandle<Object> Execution::Call(Isolate* isolate, Handle<Object> callable, | 128 MaybeHandle<Object> Execution::Call(Isolate* isolate, Handle<Object> callable, |
167 Handle<Object> receiver, int argc, | 129 Handle<Object> receiver, int argc, |
168 Handle<Object> argv[]) { | 130 Handle<Object> argv[]) { |
169 if (!callable->IsJSFunction()) { | 131 // Convert calls on global objects to be calls on the global |
170 ASSIGN_RETURN_ON_EXCEPTION(isolate, callable, | 132 // receiver instead to avoid having a 'this' pointer which refers |
171 GetFunctionDelegate(isolate, callable), Object); | 133 // directly to a global object. |
| 134 if (receiver->IsGlobalObject()) { |
| 135 receiver = |
| 136 handle(Handle<GlobalObject>::cast(receiver)->global_proxy(), isolate); |
172 } | 137 } |
173 Handle<JSFunction> func = Handle<JSFunction>::cast(callable); | 138 |
174 return Invoke(false, func, receiver, argc, argv, | 139 // api callbacks can be called directly. |
| 140 if (callable->IsJSFunction() && |
| 141 Handle<JSFunction>::cast(callable)->shared()->IsApiFunction()) { |
| 142 Handle<JSFunction> function = Handle<JSFunction>::cast(callable); |
| 143 SaveContext save(isolate); |
| 144 isolate->set_context(function->context()); |
| 145 // Do proper receiver conversion for non-strict mode api functions. |
| 146 if (!receiver->IsJSReceiver() && |
| 147 is_sloppy(function->shared()->language_mode())) { |
| 148 if (receiver->IsUndefined() || receiver->IsNull()) { |
| 149 receiver = handle(function->global_proxy(), isolate); |
| 150 } else { |
| 151 ASSIGN_RETURN_ON_EXCEPTION( |
| 152 isolate, receiver, Execution::ToObject(isolate, receiver), Object); |
| 153 } |
| 154 } |
| 155 DCHECK(function->context()->global_object()->IsGlobalObject()); |
| 156 auto value = Builtins::InvokeApiFunction(function, receiver, argc, argv); |
| 157 bool has_exception = value.is_null(); |
| 158 DCHECK(has_exception == isolate->has_pending_exception()); |
| 159 if (has_exception) { |
| 160 isolate->ReportPendingMessages(); |
| 161 return MaybeHandle<Object>(); |
| 162 } else { |
| 163 isolate->clear_pending_message(); |
| 164 } |
| 165 return value; |
| 166 } |
| 167 return Invoke(isolate, false, callable, receiver, argc, argv, |
175 isolate->factory()->undefined_value()); | 168 isolate->factory()->undefined_value()); |
176 } | 169 } |
177 | 170 |
178 | 171 |
| 172 // static |
179 MaybeHandle<Object> Execution::New(Handle<JSFunction> constructor, int argc, | 173 MaybeHandle<Object> Execution::New(Handle<JSFunction> constructor, int argc, |
180 Handle<Object> argv[]) { | 174 Handle<Object> argv[]) { |
181 return New(constructor, constructor, argc, argv); | 175 return New(constructor->GetIsolate(), constructor, constructor, argc, argv); |
182 } | 176 } |
183 | 177 |
184 | 178 |
185 MaybeHandle<Object> Execution::New(Handle<JSFunction> constructor, | 179 // static |
186 Handle<JSFunction> new_target, int argc, | 180 MaybeHandle<Object> Execution::New(Isolate* isolate, Handle<Object> constructor, |
| 181 Handle<Object> new_target, int argc, |
187 Handle<Object> argv[]) { | 182 Handle<Object> argv[]) { |
188 return Invoke(true, constructor, handle(constructor->global_proxy()), argc, | 183 return Invoke(isolate, true, constructor, |
189 argv, new_target); | 184 isolate->factory()->undefined_value(), argc, argv, new_target); |
190 } | 185 } |
191 | 186 |
192 | 187 |
193 MaybeHandle<Object> Execution::TryCall(Handle<JSFunction> func, | 188 MaybeHandle<Object> Execution::TryCall(Handle<JSFunction> func, |
194 Handle<Object> receiver, int argc, | 189 Handle<Object> receiver, int argc, |
195 Handle<Object> args[], | 190 Handle<Object> args[], |
196 MaybeHandle<Object>* exception_out) { | 191 MaybeHandle<Object>* exception_out) { |
197 bool is_termination = false; | 192 bool is_termination = false; |
198 Isolate* isolate = func->GetIsolate(); | 193 Isolate* isolate = func->GetIsolate(); |
199 MaybeHandle<Object> maybe_result; | 194 MaybeHandle<Object> maybe_result; |
(...skipping 27 matching lines...) Expand all Loading... |
227 DCHECK(!isolate->has_pending_exception()); | 222 DCHECK(!isolate->has_pending_exception()); |
228 } | 223 } |
229 | 224 |
230 // Re-request terminate execution interrupt to trigger later. | 225 // Re-request terminate execution interrupt to trigger later. |
231 if (is_termination) isolate->stack_guard()->RequestTerminateExecution(); | 226 if (is_termination) isolate->stack_guard()->RequestTerminateExecution(); |
232 | 227 |
233 return maybe_result; | 228 return maybe_result; |
234 } | 229 } |
235 | 230 |
236 | 231 |
237 // static | |
238 MaybeHandle<JSFunction> Execution::GetFunctionDelegate(Isolate* isolate, | |
239 Handle<Object> object) { | |
240 DCHECK(!object->IsJSFunction()); | |
241 if (object->IsHeapObject()) { | |
242 DisallowHeapAllocation no_gc; | |
243 | |
244 // If object is a function proxy, get its handler. Iterate if necessary. | |
245 Object* fun = *object; | |
246 while (fun->IsJSFunctionProxy()) { | |
247 fun = JSFunctionProxy::cast(fun)->call_trap(); | |
248 } | |
249 if (fun->IsJSFunction()) { | |
250 return handle(JSFunction::cast(fun), isolate); | |
251 } | |
252 | |
253 // We can also have exotic objects with [[Call]] internal methods. | |
254 if (fun->IsCallable()) { | |
255 return handle(isolate->native_context()->call_as_function_delegate(), | |
256 isolate); | |
257 } | |
258 } | |
259 | |
260 // If the Object doesn't have an instance-call handler we should | |
261 // throw a non-callable exception. | |
262 Handle<String> callsite = RenderCallSite(isolate, object); | |
263 THROW_NEW_ERROR(isolate, | |
264 NewTypeError(MessageTemplate::kCalledNonCallable, callsite), | |
265 JSFunction); | |
266 } | |
267 | |
268 | |
269 // static | |
270 MaybeHandle<JSFunction> Execution::GetConstructorDelegate( | |
271 Isolate* isolate, Handle<Object> object) { | |
272 // If you return a function from here, it will be called when an | |
273 // attempt is made to call the given object as a constructor. | |
274 | |
275 DCHECK(!object->IsJSFunction()); | |
276 if (object->IsHeapObject()) { | |
277 DisallowHeapAllocation no_gc; | |
278 | |
279 // If object is a function proxies, get its handler. Iterate if necessary. | |
280 Object* fun = *object; | |
281 while (fun->IsJSFunctionProxy()) { | |
282 // TODO(bmeurer): This should work based on [[Construct]]; our proxies | |
283 // are screwed. | |
284 fun = JSFunctionProxy::cast(fun)->call_trap(); | |
285 } | |
286 if (fun->IsJSFunction()) { | |
287 return handle(JSFunction::cast(fun), isolate); | |
288 } | |
289 | |
290 // We can also have exotic objects with [[Construct]] internal methods. | |
291 // TODO(bmeurer): This should use IsConstructor() as dictacted by the spec. | |
292 if (fun->IsCallable()) { | |
293 return handle(isolate->native_context()->call_as_constructor_delegate(), | |
294 isolate); | |
295 } | |
296 } | |
297 | |
298 // If the Object doesn't have an instance-call handler we should | |
299 // throw a non-callable exception. | |
300 Handle<String> callsite = RenderCallSite(isolate, object); | |
301 THROW_NEW_ERROR(isolate, | |
302 NewTypeError(MessageTemplate::kCalledNonCallable, callsite), | |
303 JSFunction); | |
304 } | |
305 | |
306 | |
307 // static | |
308 Handle<String> Execution::RenderCallSite(Isolate* isolate, | |
309 Handle<Object> object) { | |
310 MessageLocation location; | |
311 if (isolate->ComputeLocation(&location)) { | |
312 Zone zone; | |
313 base::SmartPointer<ParseInfo> info( | |
314 location.function()->shared()->is_function() | |
315 ? new ParseInfo(&zone, location.function()) | |
316 : new ParseInfo(&zone, location.script())); | |
317 if (Parser::ParseStatic(info.get())) { | |
318 CallPrinter printer(isolate, &zone); | |
319 const char* string = printer.Print(info->literal(), location.start_pos()); | |
320 return isolate->factory()->NewStringFromAsciiChecked(string); | |
321 } else { | |
322 isolate->clear_pending_exception(); | |
323 } | |
324 } | |
325 return Object::TypeOf(isolate, object); | |
326 } | |
327 | |
328 | |
329 void StackGuard::SetStackLimit(uintptr_t limit) { | 232 void StackGuard::SetStackLimit(uintptr_t limit) { |
330 ExecutionAccess access(isolate_); | 233 ExecutionAccess access(isolate_); |
331 // If the current limits are special (e.g. due to a pending interrupt) then | 234 // If the current limits are special (e.g. due to a pending interrupt) then |
332 // leave them alone. | 235 // leave them alone. |
333 uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit); | 236 uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit); |
334 if (thread_local_.jslimit() == thread_local_.real_jslimit_) { | 237 if (thread_local_.jslimit() == thread_local_.real_jslimit_) { |
335 thread_local_.set_jslimit(jslimit); | 238 thread_local_.set_jslimit(jslimit); |
336 } | 239 } |
337 if (thread_local_.climit() == thread_local_.real_climit_) { | 240 if (thread_local_.climit() == thread_local_.real_climit_) { |
338 thread_local_.set_climit(limit); | 241 thread_local_.set_climit(limit); |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
646 | 549 |
647 isolate_->counters()->stack_interrupts()->Increment(); | 550 isolate_->counters()->stack_interrupts()->Increment(); |
648 isolate_->counters()->runtime_profiler_ticks()->Increment(); | 551 isolate_->counters()->runtime_profiler_ticks()->Increment(); |
649 isolate_->runtime_profiler()->OptimizeNow(); | 552 isolate_->runtime_profiler()->OptimizeNow(); |
650 | 553 |
651 return isolate_->heap()->undefined_value(); | 554 return isolate_->heap()->undefined_value(); |
652 } | 555 } |
653 | 556 |
654 } // namespace internal | 557 } // namespace internal |
655 } // namespace v8 | 558 } // namespace v8 |
OLD | NEW |