Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(40)

Side by Side Diff: src/execution.cc

Issue 1360793002: [builtins] Refactor Invoke to deal with any kind of callable. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW
« src/arm/builtins-arm.cc ('K') | « src/execution.h ('k') | src/ia32/builtins-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698