| 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 |