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 "v8.h"
00029
00030 #include "api.h"
00031 #include "bootstrapper.h"
00032 #include "builtins.h"
00033 #include "ic-inl.h"
00034
00035 namespace v8 { namespace internal {
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 #define BUILTIN(name) \
00067 static Object* Builtin_##name(int __argc__, Object** __argv__) { \
00068 Handle<Object> receiver(&__argv__[0]);
00069
00070
00071
00072
00073 static inline Object* __builtin_arg__(int n, int argc, Object** argv) {
00074 ASSERT(n >= 0);
00075 return (argc > n) ? argv[-n] : Heap::undefined_value();
00076 }
00077
00078
00079
00080
00081 #define BUILTIN_ARG(n) (__builtin_arg__(n, __argc__, __argv__))
00082
00083
00084 #define BUILTIN_END \
00085 return Heap::undefined_value(); \
00086 }
00087
00088
00089
00090
00091
00092 static inline bool CalledAsConstructor() {
00093 StackFrameIterator it;
00094 ASSERT(it.frame()->is_exit());
00095 it.Advance();
00096 StackFrame* frame = it.frame();
00097 return frame->is_construct();
00098 }
00099
00100
00101
00102
00103
00104 Handle<Code> Builtins::GetCode(JavaScript id, bool* resolved) {
00105 Code* code = Builtins::builtin(Builtins::Illegal);
00106 *resolved = false;
00107
00108 if (Top::context() != NULL) {
00109 Object* object = Top::builtins()->javascript_builtin(id);
00110 if (object->IsJSFunction()) {
00111 Handle<JSFunction> function(JSFunction::cast(object));
00112
00113 ASSERT(function->shared()->formal_parameter_count() ==
00114 Builtins::GetArgumentsCount(id));
00115 if (function->is_compiled() || CompileLazy(function, CLEAR_EXCEPTION)) {
00116 code = function->code();
00117 *resolved = true;
00118 }
00119 }
00120 }
00121
00122 return Handle<Code>(code);
00123 }
00124
00125
00126 BUILTIN(Illegal) {
00127 UNREACHABLE();
00128 }
00129 BUILTIN_END
00130
00131
00132 BUILTIN(EmptyFunction) {
00133 }
00134 BUILTIN_END
00135
00136
00137 BUILTIN(ArrayCode) {
00138 JSArray* array;
00139 if (CalledAsConstructor()) {
00140 array = JSArray::cast(*receiver);
00141 } else {
00142
00143 JSFunction* constructor =
00144 Top::context()->global_context()->array_function();
00145 Object* obj = Heap::AllocateJSObject(constructor);
00146 if (obj->IsFailure()) return obj;
00147 array = JSArray::cast(obj);
00148 }
00149
00150
00151
00152
00153
00154 if (__argc__ == 2) {
00155 Object* obj = BUILTIN_ARG(1);
00156 if (obj->IsSmi()) {
00157 int len = Smi::cast(obj)->value();
00158 if (len >= 0 && len < JSObject::kMaxFastElementsLength) {
00159 Object* obj = Heap::AllocateFixedArrayWithHoles(len);
00160 if (obj->IsFailure()) return obj;
00161 array->SetContent(FixedArray::cast(obj));
00162 return array;
00163 }
00164 }
00165
00166 obj = array->Initialize(0);
00167 if (obj->IsFailure()) return obj;
00168 if (__argc__ == 2) return array->SetElementsLength(BUILTIN_ARG(1));
00169 }
00170
00171
00172 if (__argc__ == 1) return array->Initialize(4);
00173
00174
00175 int number_of_elements = __argc__ - 1;
00176 Smi* len = Smi::FromInt(number_of_elements);
00177 Object* obj = Heap::AllocateFixedArrayWithHoles(len->value());
00178 if (obj->IsFailure()) return obj;
00179 FixedArray* elms = FixedArray::cast(obj);
00180 WriteBarrierMode mode = elms->GetWriteBarrierMode();
00181
00182 for (int index = 0; index < number_of_elements; index++) {
00183 elms->set(index, BUILTIN_ARG(index+1), mode);
00184 }
00185
00186
00187 array->set_elements(FixedArray::cast(obj));
00188 array->set_length(len, SKIP_WRITE_BARRIER);
00189
00190 return array;
00191 }
00192 BUILTIN_END
00193
00194
00195 BUILTIN(ArrayPush) {
00196 JSArray* array = JSArray::cast(*receiver);
00197 ASSERT(array->HasFastElements());
00198
00199
00200 int len = Smi::cast(array->length())->value();
00201
00202
00203 int new_length = len + __argc__ - 1;
00204 FixedArray* elms = FixedArray::cast(array->elements());
00205
00206 if (new_length <= elms->length()) {
00207
00208 for (int index = 0; index < __argc__ - 1; index++) {
00209 elms->set(index + len, BUILTIN_ARG(index+1));
00210 }
00211 } else {
00212
00213 int capacity = new_length + (new_length >> 1) + 16;
00214 Object* obj = Heap::AllocateFixedArrayWithHoles(capacity);
00215 if (obj->IsFailure()) return obj;
00216 FixedArray* new_elms = FixedArray::cast(obj);
00217 WriteBarrierMode mode = new_elms->GetWriteBarrierMode();
00218
00219 for (int i = 0; i < len; i++) new_elms->set(i, elms->get(i), mode);
00220
00221 for (int index = 0; index < __argc__ - 1; index++) {
00222 new_elms->set(index + len, BUILTIN_ARG(index+1), mode);
00223 }
00224
00225 array->set_elements(new_elms);
00226 }
00227
00228 array->set_length(Smi::FromInt(new_length), SKIP_WRITE_BARRIER);
00229 return array->length();
00230 }
00231 BUILTIN_END
00232
00233
00234 BUILTIN(ArrayPop) {
00235 JSArray* array = JSArray::cast(*receiver);
00236 ASSERT(array->HasFastElements());
00237 Object* undefined = Heap::undefined_value();
00238
00239 int len = Smi::cast(array->length())->value();
00240 if (len == 0) return undefined;
00241
00242
00243 FixedArray* elms = FixedArray::cast(array->elements());
00244 Object* top = elms->get(len - 1);
00245
00246
00247 array->set_length(Smi::FromInt(len - 1), SKIP_WRITE_BARRIER);
00248
00249 if (!top->IsTheHole()) {
00250
00251 elms->set_the_hole(len - 1);
00252 return top;
00253 }
00254
00255
00256 JSFunction* array_function =
00257 Top::context()->global_context()->array_function();
00258 JSObject* prototype = JSObject::cast(array_function->prototype());
00259 top = prototype->GetElement(len - 1);
00260
00261 return top;
00262 }
00263 BUILTIN_END
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276 static inline Object* TypeCheck(int argc,
00277 Object** argv,
00278 FunctionTemplateInfo* info) {
00279 Object* recv = argv[0];
00280 Object* sig_obj = info->signature();
00281 if (sig_obj->IsUndefined()) return recv;
00282 SignatureInfo* sig = SignatureInfo::cast(sig_obj);
00283
00284 Object* recv_type = sig->receiver();
00285
00286 Object* holder = recv;
00287 if (!recv_type->IsUndefined()) {
00288 for (; holder != Heap::null_value(); holder = holder->GetPrototype()) {
00289 if (holder->IsInstanceOf(FunctionTemplateInfo::cast(recv_type))) {
00290 break;
00291 }
00292 }
00293 if (holder == Heap::null_value()) return holder;
00294 }
00295 Object* args_obj = sig->args();
00296
00297 if (args_obj->IsUndefined()) return holder;
00298 FixedArray* args = FixedArray::cast(args_obj);
00299 int length = args->length();
00300 if (argc <= length) length = argc - 1;
00301 for (int i = 0; i < length; i++) {
00302 Object* argtype = args->get(i);
00303 if (argtype->IsUndefined()) continue;
00304 Object** arg = &argv[-1 - i];
00305 Object* current = *arg;
00306 for (; current != Heap::null_value(); current = current->GetPrototype()) {
00307 if (current->IsInstanceOf(FunctionTemplateInfo::cast(argtype))) {
00308 *arg = current;
00309 break;
00310 }
00311 }
00312 if (current == Heap::null_value()) *arg = Heap::undefined_value();
00313 }
00314 return holder;
00315 }
00316
00317
00318 BUILTIN(HandleApiCall) {
00319 HandleScope scope;
00320 bool is_construct = CalledAsConstructor();
00321
00322
00323
00324
00325 Handle<JSFunction> function =
00326 Handle<JSFunction>(JSFunction::cast(Builtins::builtin_passed_function));
00327
00328 if (is_construct) {
00329 Handle<FunctionTemplateInfo> desc =
00330 Handle<FunctionTemplateInfo>(
00331 FunctionTemplateInfo::cast(function->shared()->function_data()));
00332 bool pending_exception = false;
00333 Factory::ConfigureInstance(desc, Handle<JSObject>::cast(receiver),
00334 &pending_exception);
00335 ASSERT(Top::has_pending_exception() == pending_exception);
00336 if (pending_exception) return Failure::Exception();
00337 }
00338
00339 FunctionTemplateInfo* fun_data =
00340 FunctionTemplateInfo::cast(function->shared()->function_data());
00341 Object* raw_holder = TypeCheck(__argc__, __argv__, fun_data);
00342
00343 if (raw_holder->IsNull()) {
00344
00345 Handle<Object> obj =
00346 Factory::NewTypeError("illegal_invocation", HandleVector(&function, 1));
00347 return Top::Throw(*obj);
00348 }
00349
00350 Object* raw_call_data = fun_data->call_code();
00351 if (!raw_call_data->IsUndefined()) {
00352 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
00353 Object* callback_obj = call_data->callback();
00354 v8::InvocationCallback callback =
00355 v8::ToCData<v8::InvocationCallback>(callback_obj);
00356 Object* data_obj = call_data->data();
00357 Object* result;
00358
00359 v8::Local<v8::Object> self =
00360 v8::Utils::ToLocal(Handle<JSObject>::cast(receiver));
00361 Handle<Object> data_handle(data_obj);
00362 v8::Local<v8::Value> data = v8::Utils::ToLocal(data_handle);
00363 ASSERT(raw_holder->IsJSObject());
00364 v8::Local<v8::Function> callee = v8::Utils::ToLocal(function);
00365 Handle<JSObject> holder_handle(JSObject::cast(raw_holder));
00366 v8::Local<v8::Object> holder = v8::Utils::ToLocal(holder_handle);
00367 LOG(ApiObjectAccess("call", JSObject::cast(*receiver)));
00368 v8::Arguments args = v8::ImplementationUtilities::NewArguments(
00369 data,
00370 holder,
00371 callee,
00372 is_construct,
00373 reinterpret_cast<void**>(__argv__ - 1),
00374 __argc__ - 1);
00375
00376 v8::Handle<v8::Value> value;
00377 {
00378
00379 VMState state(OTHER);
00380 value = callback(args);
00381 }
00382 if (value.IsEmpty()) {
00383 result = Heap::undefined_value();
00384 } else {
00385 result = *reinterpret_cast<Object**>(*value);
00386 }
00387
00388 RETURN_IF_SCHEDULED_EXCEPTION();
00389 if (!is_construct || result->IsJSObject()) return result;
00390 }
00391
00392 return *receiver;
00393 }
00394 BUILTIN_END
00395
00396
00397
00398
00399 BUILTIN(HandleApiCallAsFunction) {
00400
00401 ASSERT(!CalledAsConstructor());
00402
00403
00404 JSObject* obj = JSObject::cast(*receiver);
00405
00406
00407
00408 ASSERT(obj->map()->has_instance_call_handler());
00409 JSFunction* constructor = JSFunction::cast(obj->map()->constructor());
00410 Object* template_info = constructor->shared()->function_data();
00411 Object* handler =
00412 FunctionTemplateInfo::cast(template_info)->instance_call_handler();
00413 ASSERT(!handler->IsUndefined());
00414 CallHandlerInfo* call_data = CallHandlerInfo::cast(handler);
00415 Object* callback_obj = call_data->callback();
00416 v8::InvocationCallback callback =
00417 v8::ToCData<v8::InvocationCallback>(callback_obj);
00418
00419
00420 Object* data_obj = call_data->data();
00421 Object* result;
00422 { HandleScope scope;
00423 v8::Local<v8::Object> self =
00424 v8::Utils::ToLocal(Handle<JSObject>::cast(receiver));
00425 Handle<Object> data_handle(data_obj);
00426 v8::Local<v8::Value> data = v8::Utils::ToLocal(data_handle);
00427 Handle<JSFunction> callee_handle(constructor);
00428 v8::Local<v8::Function> callee = v8::Utils::ToLocal(callee_handle);
00429 LOG(ApiObjectAccess("call non-function", JSObject::cast(*receiver)));
00430 v8::Arguments args = v8::ImplementationUtilities::NewArguments(
00431 data,
00432 self,
00433 callee,
00434 false,
00435 reinterpret_cast<void**>(__argv__ - 1),
00436 __argc__ - 1);
00437 v8::Handle<v8::Value> value;
00438 {
00439
00440 VMState state(OTHER);
00441 value = callback(args);
00442 }
00443 if (value.IsEmpty()) {
00444 result = Heap::undefined_value();
00445 } else {
00446 result = *reinterpret_cast<Object**>(*value);
00447 }
00448 }
00449
00450 RETURN_IF_SCHEDULED_EXCEPTION();
00451 return result;
00452 }
00453 BUILTIN_END
00454
00455
00456
00457
00458
00459 Object* Builtins::builtin_passed_function;
00460
00461
00462
00463 static void Generate_LoadIC_ArrayLength(MacroAssembler* masm) {
00464 LoadIC::GenerateArrayLength(masm);
00465 }
00466
00467
00468 static void Generate_LoadIC_StringLength(MacroAssembler* masm) {
00469 LoadIC::GenerateStringLength(masm);
00470 }
00471
00472
00473 static void Generate_LoadIC_FunctionPrototype(MacroAssembler* masm) {
00474 LoadIC::GenerateFunctionPrototype(masm);
00475 }
00476
00477
00478 static void Generate_LoadIC_Initialize(MacroAssembler* masm) {
00479 LoadIC::GenerateInitialize(masm);
00480 }
00481
00482
00483 static void Generate_LoadIC_PreMonomorphic(MacroAssembler* masm) {
00484 LoadIC::GeneratePreMonomorphic(masm);
00485 }
00486
00487
00488 static void Generate_LoadIC_Miss(MacroAssembler* masm) {
00489 LoadIC::GenerateMiss(masm);
00490 }
00491
00492
00493 static void Generate_LoadIC_Megamorphic(MacroAssembler* masm) {
00494 LoadIC::GenerateMegamorphic(masm);
00495 }
00496
00497
00498 static void Generate_LoadIC_Normal(MacroAssembler* masm) {
00499 LoadIC::GenerateNormal(masm);
00500 }
00501
00502
00503 static void Generate_KeyedLoadIC_Initialize(MacroAssembler* masm) {
00504 KeyedLoadIC::GenerateInitialize(masm);
00505 }
00506
00507
00508 static void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
00509 KeyedLoadIC::GenerateMiss(masm);
00510 }
00511
00512
00513 static void Generate_KeyedLoadIC_Generic(MacroAssembler* masm) {
00514 KeyedLoadIC::GenerateGeneric(masm);
00515 }
00516
00517
00518 static void Generate_KeyedLoadIC_PreMonomorphic(MacroAssembler* masm) {
00519 KeyedLoadIC::GeneratePreMonomorphic(masm);
00520 }
00521
00522
00523 static void Generate_StoreIC_Initialize(MacroAssembler* masm) {
00524 StoreIC::GenerateInitialize(masm);
00525 }
00526
00527
00528 static void Generate_StoreIC_Miss(MacroAssembler* masm) {
00529 StoreIC::GenerateMiss(masm);
00530 }
00531
00532
00533 static void Generate_StoreIC_ExtendStorage(MacroAssembler* masm) {
00534 StoreIC::GenerateExtendStorage(masm);
00535 }
00536
00537 static void Generate_StoreIC_Megamorphic(MacroAssembler* masm) {
00538 StoreIC::GenerateMegamorphic(masm);
00539 }
00540
00541
00542 static void Generate_KeyedStoreIC_Generic(MacroAssembler* masm) {
00543 KeyedStoreIC::GenerateGeneric(masm);
00544 }
00545
00546
00547 static void Generate_KeyedStoreIC_ExtendStorage(MacroAssembler* masm) {
00548 KeyedStoreIC::GenerateExtendStorage(masm);
00549 }
00550
00551
00552 static void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
00553 KeyedStoreIC::GenerateMiss(masm);
00554 }
00555
00556
00557 static void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) {
00558 KeyedStoreIC::GenerateInitialize(masm);
00559 }
00560
00561
00562 Object* Builtins::builtins_[builtin_count] = { NULL, };
00563 const char* Builtins::names_[builtin_count] = { NULL, };
00564
00565 #define DEF_ENUM_C(name) FUNCTION_ADDR(Builtin_##name),
00566 Address Builtins::c_functions_[cfunction_count] = {
00567 BUILTIN_LIST_C(DEF_ENUM_C)
00568 };
00569 #undef DEF_ENUM_C
00570
00571 #define DEF_JS_NAME(name, ignore) #name,
00572 #define DEF_JS_ARGC(ignore, argc) argc,
00573 const char* Builtins::javascript_names_[id_count] = {
00574 BUILTINS_LIST_JS(DEF_JS_NAME)
00575 };
00576
00577 int Builtins::javascript_argc_[id_count] = {
00578 BUILTINS_LIST_JS(DEF_JS_ARGC)
00579 };
00580 #undef DEF_JS_NAME
00581 #undef DEF_JS_ARGC
00582
00583 static bool is_initialized = false;
00584 void Builtins::Setup(bool create_heap_objects) {
00585 ASSERT(!is_initialized);
00586
00587
00588 HandleScope scope;
00589
00590 struct BuiltinDesc {
00591 byte* generator;
00592 byte* c_code;
00593 const char* s_name;
00594 int name;
00595 Code::Flags flags;
00596 };
00597
00598 #define DEF_FUNCTION_PTR_C(name) \
00599 { FUNCTION_ADDR(Generate_Adaptor), \
00600 FUNCTION_ADDR(Builtin_##name), \
00601 #name, \
00602 c_##name, \
00603 Code::ComputeFlags(Code::BUILTIN) \
00604 },
00605
00606 #define DEF_FUNCTION_PTR_A(name, kind, state) \
00607 { FUNCTION_ADDR(Generate_##name), \
00608 NULL, \
00609 #name, \
00610 name, \
00611 Code::ComputeFlags(Code::kind, state) \
00612 },
00613
00614
00615 static BuiltinDesc functions[] = {
00616 BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
00617 BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
00618
00619 { NULL, NULL, NULL, builtin_count, static_cast<Code::Flags>(0) }
00620 };
00621
00622 #undef DEF_FUNCTION_PTR_C
00623 #undef DEF_FUNCTION_PTR_A
00624
00625
00626
00627 byte buffer[4*KB];
00628
00629
00630
00631 for (int i = 0; i < builtin_count; i++) {
00632 if (create_heap_objects) {
00633 MacroAssembler masm(buffer, sizeof buffer);
00634
00635 typedef void (*Generator)(MacroAssembler*, int);
00636 Generator g = FUNCTION_CAST<Generator>(functions[i].generator);
00637
00638
00639
00640 g(&masm, functions[i].name);
00641
00642 CodeDesc desc;
00643 masm.GetCode(&desc);
00644 Code::Flags flags = functions[i].flags;
00645 Object* code;
00646 {
00647
00648
00649 AlwaysAllocateScope __scope__;
00650 code = Heap::CreateCode(desc, NULL, flags);
00651 if (code->IsFailure()) {
00652 v8::internal::V8::FatalProcessOutOfMemory("CreateCode");
00653 }
00654 }
00655
00656
00657 Bootstrapper::AddFixup(Code::cast(code), &masm);
00658
00659 LOG(CodeCreateEvent("Builtin", Code::cast(code), functions[i].s_name));
00660 builtins_[i] = code;
00661 #ifdef DEBUG
00662 if (FLAG_print_builtin_code) {
00663 PrintF("Builtin: %s\n", functions[i].s_name);
00664 code->Print();
00665 PrintF("\n");
00666 }
00667 #endif
00668 } else {
00669
00670 builtins_[i] = NULL;
00671 }
00672 names_[i] = functions[i].s_name;
00673 }
00674
00675
00676 is_initialized = true;
00677 }
00678
00679
00680 void Builtins::TearDown() {
00681 is_initialized = false;
00682 }
00683
00684
00685 void Builtins::IterateBuiltins(ObjectVisitor* v) {
00686 v->VisitPointers(&builtins_[0], &builtins_[0] + builtin_count);
00687 }
00688
00689
00690 const char* Builtins::Lookup(byte* pc) {
00691 if (is_initialized) {
00692 for (int i = 0; i < builtin_count; i++) {
00693 Code* entry = Code::cast(builtins_[i]);
00694 if (entry->contains(pc)) {
00695 return names_[i];
00696 }
00697 }
00698 }
00699 return NULL;
00700 }
00701
00702
00703 } }