00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <stdlib.h>
00029
00030 #include "v8.h"
00031
00032 #include "api.h"
00033 #include "codegen-inl.h"
00034
00035 #if defined(ARM) || defined (__arm__) || defined(__thumb__)
00036 #include "simulator-arm.h"
00037 #else // ia32
00038 #include "simulator-ia32.h"
00039 #endif
00040
00041 namespace v8 { namespace internal {
00042
00043
00044 static Handle<Object> Invoke(bool construct,
00045 Handle<JSFunction> func,
00046 Handle<Object> receiver,
00047 int argc,
00048 Object*** args,
00049 bool* has_pending_exception) {
00050
00051 ASSERT(!func->IsBoilerplate());
00052
00053
00054 VMState state(JS);
00055
00056
00057 StackGuard guard;
00058
00059
00060 Object* value = reinterpret_cast<Object*>(kZapValue);
00061
00062 typedef Object* (*JSEntryFunction)(
00063 byte* entry,
00064 Object* function,
00065 Object* receiver,
00066 int argc,
00067 Object*** args);
00068
00069 Handle<Code> code;
00070 if (construct) {
00071 JSConstructEntryStub stub;
00072 code = stub.GetCode();
00073 } else {
00074 JSEntryStub stub;
00075 code = stub.GetCode();
00076 }
00077
00078 {
00079
00080
00081 SaveContext save;
00082 NoHandleAllocation na;
00083 JSEntryFunction entry = FUNCTION_CAST<JSEntryFunction>(code->entry());
00084
00085
00086 value = CALL_GENERATED_CODE(entry, func->code()->entry(), *func,
00087 *receiver, argc, args);
00088 }
00089
00090 #ifdef DEBUG
00091 value->Verify();
00092 #endif
00093
00094
00095 *has_pending_exception = value->IsException();
00096 ASSERT(*has_pending_exception == Top::has_pending_exception());
00097 if (*has_pending_exception) {
00098 Top::setup_external_caught();
00099 }
00100
00101
00102
00103
00104
00105 if (*has_pending_exception) {
00106 if (Top::pending_exception() == Failure::OutOfMemoryException()) {
00107 Top::context()->mark_out_of_memory();
00108 }
00109 }
00110
00111 return Handle<Object>(value);
00112 }
00113
00114
00115 Handle<Object> Execution::Call(Handle<JSFunction> func,
00116 Handle<Object> receiver,
00117 int argc,
00118 Object*** args,
00119 bool* pending_exception) {
00120 return Invoke(false, func, receiver, argc, args, pending_exception);
00121 }
00122
00123
00124 Handle<Object> Execution::New(Handle<JSFunction> func, int argc,
00125 Object*** args, bool* pending_exception) {
00126 return Invoke(true, func, Top::global(), argc, args, pending_exception);
00127 }
00128
00129
00130 Handle<Object> Execution::TryCall(Handle<JSFunction> func,
00131 Handle<Object> receiver,
00132 int argc,
00133 Object*** args,
00134 bool* caught_exception) {
00135
00136
00137
00138
00139 v8::TryCatch catcher;
00140 catcher.SetVerbose(false);
00141 catcher.SetCaptureMessage(false);
00142
00143 Handle<Object> result = Invoke(false, func, receiver, argc, args,
00144 caught_exception);
00145
00146 if (*caught_exception) {
00147 ASSERT(catcher.HasCaught());
00148 ASSERT(Top::has_pending_exception());
00149 ASSERT(Top::external_caught_exception());
00150 Top::optional_reschedule_exception(true);
00151 result = v8::Utils::OpenHandle(*catcher.Exception());
00152 }
00153
00154 ASSERT(!Top::has_pending_exception());
00155 ASSERT(!Top::external_caught_exception());
00156 return result;
00157 }
00158
00159
00160 Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) {
00161 ASSERT(!object->IsJSFunction());
00162
00163
00164
00165
00166
00167
00168
00169 if (FLAG_call_regexp) {
00170 bool is_regexp =
00171 object->IsHeapObject() &&
00172 (HeapObject::cast(*object)->map()->constructor() ==
00173 *Top::regexp_function());
00174
00175 if (is_regexp) {
00176 Handle<String> exec = Factory::exec_symbol();
00177 return Handle<Object>(object->GetProperty(*exec));
00178 }
00179 }
00180
00181
00182
00183 if (object->IsHeapObject() &&
00184 HeapObject::cast(*object)->map()->has_instance_call_handler()) {
00185 return Handle<JSFunction>(
00186 Top::global_context()->call_as_function_delegate());
00187 }
00188
00189 return Factory::undefined_value();
00190 }
00191
00192
00193
00194 StackGuard::ThreadLocal StackGuard::thread_local_;
00195
00196
00197 StackGuard::StackGuard() {
00198 ExecutionAccess access;
00199 if (thread_local_.nesting_++ == 0 &&
00200 thread_local_.jslimit_ != kInterruptLimit) {
00201
00202 ASSERT(thread_local_.jslimit_ == kIllegalLimit);
00203 ASSERT(thread_local_.climit_ == kIllegalLimit);
00204
00205 thread_local_.initial_jslimit_ = thread_local_.jslimit_ =
00206 GENERATED_CODE_STACK_LIMIT(kLimitSize);
00207
00208
00209 thread_local_.initial_climit_ = thread_local_.climit_ =
00210 reinterpret_cast<uintptr_t>(this) >= kLimitSize ?
00211 reinterpret_cast<uintptr_t>(this) - kLimitSize : 0;
00212
00213 if (thread_local_.interrupt_flags_ != 0) {
00214 set_limits(kInterruptLimit, access);
00215 }
00216 }
00217
00218 ASSERT(thread_local_.jslimit_ != kIllegalLimit &&
00219 thread_local_.climit_ != kIllegalLimit);
00220 }
00221
00222
00223 StackGuard::~StackGuard() {
00224 ExecutionAccess access;
00225 if (--thread_local_.nesting_ == 0) {
00226 set_limits(kIllegalLimit, access);
00227 }
00228 }
00229
00230
00231 bool StackGuard::IsStackOverflow() {
00232 ExecutionAccess access;
00233 return (thread_local_.jslimit_ != kInterruptLimit &&
00234 thread_local_.climit_ != kInterruptLimit);
00235 }
00236
00237
00238 void StackGuard::EnableInterrupts() {
00239 ExecutionAccess access;
00240 if (IsSet(access)) {
00241 set_limits(kInterruptLimit, access);
00242 }
00243 }
00244
00245
00246 void StackGuard::SetStackLimit(uintptr_t limit) {
00247 ExecutionAccess access;
00248
00249
00250 if (thread_local_.jslimit_ == thread_local_.initial_jslimit_) {
00251 thread_local_.jslimit_ = limit;
00252 }
00253 if (thread_local_.climit_ == thread_local_.initial_climit_) {
00254 thread_local_.climit_ = limit;
00255 }
00256 thread_local_.initial_climit_ = limit;
00257 thread_local_.initial_jslimit_ = limit;
00258 }
00259
00260
00261 void StackGuard::DisableInterrupts() {
00262 ExecutionAccess access;
00263 reset_limits(access);
00264 }
00265
00266
00267 bool StackGuard::IsSet(const ExecutionAccess& lock) {
00268 return thread_local_.interrupt_flags_ != 0;
00269 }
00270
00271
00272 bool StackGuard::IsInterrupted() {
00273 ExecutionAccess access;
00274 return thread_local_.interrupt_flags_ & INTERRUPT;
00275 }
00276
00277
00278 void StackGuard::Interrupt() {
00279 ExecutionAccess access;
00280 thread_local_.interrupt_flags_ |= INTERRUPT;
00281 set_limits(kInterruptLimit, access);
00282 }
00283
00284
00285 bool StackGuard::IsPreempted() {
00286 ExecutionAccess access;
00287 return thread_local_.interrupt_flags_ & PREEMPT;
00288 }
00289
00290
00291 void StackGuard::Preempt() {
00292 ExecutionAccess access;
00293 thread_local_.interrupt_flags_ |= PREEMPT;
00294 set_limits(kInterruptLimit, access);
00295 }
00296
00297
00298 bool StackGuard::IsDebugBreak() {
00299 ExecutionAccess access;
00300 return thread_local_.interrupt_flags_ & DEBUGBREAK;
00301 }
00302
00303
00304 void StackGuard::DebugBreak() {
00305 ExecutionAccess access;
00306 thread_local_.interrupt_flags_ |= DEBUGBREAK;
00307 set_limits(kInterruptLimit, access);
00308 }
00309
00310
00311 void StackGuard::Continue(InterruptFlag after_what) {
00312 ExecutionAccess access;
00313 thread_local_.interrupt_flags_ &= ~static_cast<int>(after_what);
00314 if (thread_local_.interrupt_flags_ == 0) {
00315 reset_limits(access);
00316 }
00317 }
00318
00319
00320 int StackGuard::ArchiveSpacePerThread() {
00321 return sizeof(ThreadLocal);
00322 }
00323
00324
00325 char* StackGuard::ArchiveStackGuard(char* to) {
00326 ExecutionAccess access;
00327 memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
00328 ThreadLocal blank;
00329 thread_local_ = blank;
00330 return to + sizeof(ThreadLocal);
00331 }
00332
00333
00334 char* StackGuard::RestoreStackGuard(char* from) {
00335 ExecutionAccess access;
00336 memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
00337 return from + sizeof(ThreadLocal);
00338 }
00339
00340
00341
00342
00343 #define RETURN_NATIVE_CALL(name, argc, argv, has_pending_exception) \
00344 do { \
00345 Object** args[argc] = argv; \
00346 ASSERT(has_pending_exception != NULL); \
00347 return Call(Top::name##_fun(), Top::builtins(), argc, args, \
00348 has_pending_exception); \
00349 } while (false)
00350
00351
00352 Handle<Object> Execution::ToBoolean(Handle<Object> obj) {
00353
00354 if (obj->IsBoolean()) return obj;
00355 bool result = true;
00356 if (obj->IsString()) {
00357 result = Handle<String>::cast(obj)->length() != 0;
00358 } else if (obj->IsNull() || obj->IsUndefined()) {
00359 result = false;
00360 } else if (obj->IsNumber()) {
00361 double value = obj->Number();
00362 result = !((value == 0) || isnan(value));
00363 }
00364 return Handle<Object>(Heap::ToBoolean(result));
00365 }
00366
00367
00368 Handle<Object> Execution::ToNumber(Handle<Object> obj, bool* exc) {
00369 RETURN_NATIVE_CALL(to_number, 1, { obj.location() }, exc);
00370 }
00371
00372
00373 Handle<Object> Execution::ToString(Handle<Object> obj, bool* exc) {
00374 RETURN_NATIVE_CALL(to_string, 1, { obj.location() }, exc);
00375 }
00376
00377
00378 Handle<Object> Execution::ToDetailString(Handle<Object> obj, bool* exc) {
00379 RETURN_NATIVE_CALL(to_detail_string, 1, { obj.location() }, exc);
00380 }
00381
00382
00383 Handle<Object> Execution::ToObject(Handle<Object> obj, bool* exc) {
00384 if (obj->IsJSObject()) return obj;
00385 RETURN_NATIVE_CALL(to_object, 1, { obj.location() }, exc);
00386 }
00387
00388
00389 Handle<Object> Execution::ToInteger(Handle<Object> obj, bool* exc) {
00390 RETURN_NATIVE_CALL(to_integer, 1, { obj.location() }, exc);
00391 }
00392
00393
00394 Handle<Object> Execution::ToUint32(Handle<Object> obj, bool* exc) {
00395 RETURN_NATIVE_CALL(to_uint32, 1, { obj.location() }, exc);
00396 }
00397
00398
00399 Handle<Object> Execution::ToInt32(Handle<Object> obj, bool* exc) {
00400 RETURN_NATIVE_CALL(to_int32, 1, { obj.location() }, exc);
00401 }
00402
00403
00404 Handle<Object> Execution::NewDate(double time, bool* exc) {
00405 Handle<Object> time_obj = Factory::NewNumber(time);
00406 RETURN_NATIVE_CALL(create_date, 1, { time_obj.location() }, exc);
00407 }
00408
00409
00410 #undef RETURN_NATIVE_CALL
00411
00412
00413 Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) {
00414 int int_index = static_cast<int>(index);
00415 if (int_index < 0 || int_index >= string->length()) {
00416 return Factory::undefined_value();
00417 }
00418
00419 Handle<Object> char_at =
00420 GetProperty(Top::builtins(), Factory::char_at_symbol());
00421 if (!char_at->IsJSFunction()) {
00422 return Factory::undefined_value();
00423 }
00424
00425 bool caught_exception;
00426 Handle<Object> index_object = Factory::NewNumberFromInt(int_index);
00427 Object** index_arg[] = { index_object.location() };
00428 Handle<Object> result = TryCall(Handle<JSFunction>::cast(char_at),
00429 string,
00430 ARRAY_SIZE(index_arg),
00431 index_arg,
00432 &caught_exception);
00433 if (caught_exception) {
00434 return Factory::undefined_value();
00435 }
00436 return result;
00437 }
00438
00439
00440 Handle<JSFunction> Execution::InstantiateFunction(
00441 Handle<FunctionTemplateInfo> data, bool* exc) {
00442
00443 int serial_number = Smi::cast(data->serial_number())->value();
00444 Object* elm =
00445 Top::global_context()->function_cache()->GetElement(serial_number);
00446 if (!elm->IsUndefined()) return Handle<JSFunction>(JSFunction::cast(elm));
00447
00448 Object** args[1] = { Handle<Object>::cast(data).location() };
00449 Handle<Object> result =
00450 Call(Top::instantiate_fun(), Top::builtins(), 1, args, exc);
00451 if (*exc) return Handle<JSFunction>::null();
00452 return Handle<JSFunction>::cast(result);
00453 }
00454
00455
00456 Handle<JSObject> Execution::InstantiateObject(Handle<ObjectTemplateInfo> data,
00457 bool* exc) {
00458 if (data->property_list()->IsUndefined() &&
00459 !data->constructor()->IsUndefined()) {
00460 Object* result;
00461 {
00462 HandleScope scope;
00463 Handle<FunctionTemplateInfo> cons_template =
00464 Handle<FunctionTemplateInfo>(
00465 FunctionTemplateInfo::cast(data->constructor()));
00466 Handle<JSFunction> cons = InstantiateFunction(cons_template, exc);
00467 if (*exc) return Handle<JSObject>::null();
00468 Handle<Object> value = New(cons, 0, NULL, exc);
00469 if (*exc) return Handle<JSObject>::null();
00470 result = *value;
00471 }
00472 ASSERT(!*exc);
00473 return Handle<JSObject>(JSObject::cast(result));
00474 } else {
00475 Object** args[1] = { Handle<Object>::cast(data).location() };
00476 Handle<Object> result =
00477 Call(Top::instantiate_fun(), Top::builtins(), 1, args, exc);
00478 if (*exc) return Handle<JSObject>::null();
00479 return Handle<JSObject>::cast(result);
00480 }
00481 }
00482
00483
00484 void Execution::ConfigureInstance(Handle<Object> instance,
00485 Handle<Object> instance_template,
00486 bool* exc) {
00487 Object** args[2] = { instance.location(), instance_template.location() };
00488 Execution::Call(Top::configure_instance_fun(), Top::builtins(), 2, args, exc);
00489 }
00490
00491
00492 Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
00493 Handle<JSFunction> fun,
00494 Handle<Object> pos,
00495 Handle<Object> is_global) {
00496 const int argc = 4;
00497 Object** args[argc] = { recv.location(),
00498 Handle<Object>::cast(fun).location(),
00499 pos.location(),
00500 is_global.location() };
00501 bool caught_exception = false;
00502 Handle<Object> result = TryCall(Top::get_stack_trace_line_fun(),
00503 Top::builtins(), argc, args,
00504 &caught_exception);
00505 if (caught_exception || !result->IsString()) return Factory::empty_symbol();
00506 return Handle<String>::cast(result);
00507 }
00508
00509
00510
00511
00512 const char* GCExtension::kSource = "native function gc();";
00513
00514
00515 v8::Handle<v8::FunctionTemplate> GCExtension::GetNativeFunction(
00516 v8::Handle<v8::String> str) {
00517 return v8::FunctionTemplate::New(GCExtension::GC);
00518 }
00519
00520
00521 v8::Handle<v8::Value> GCExtension::GC(const v8::Arguments& args) {
00522
00523 Heap::CollectGarbage(0, OLD_DATA_SPACE);
00524 return v8::Undefined();
00525 }
00526
00527
00528 static GCExtension kGCExtension;
00529 v8::DeclareExtension kGCExtensionDeclaration(&kGCExtension);
00530
00531 } }