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 "arguments.h"
00032 #include "ic-inl.h"
00033 #include "stub-cache.h"
00034
00035 namespace v8 { namespace internal {
00036
00037
00038
00039
00040
00041 StubCache::Entry StubCache::primary_[StubCache::kPrimaryTableSize];
00042 StubCache::Entry StubCache::secondary_[StubCache::kSecondaryTableSize];
00043
00044 void StubCache::Initialize(bool create_heap_objects) {
00045 ASSERT(IsPowerOf2(kPrimaryTableSize));
00046 ASSERT(IsPowerOf2(kSecondaryTableSize));
00047 if (create_heap_objects) {
00048 HandleScope scope;
00049 Clear();
00050 }
00051 }
00052
00053
00054 Code* StubCache::Set(String* name, Map* map, Code* code) {
00055
00056 Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
00057
00058
00059
00060 ASSERT(!Heap::InNewSpace(name));
00061 ASSERT(name->IsSymbol());
00062
00063
00064
00065
00066
00067 ASSERT(Code::ExtractICStateFromFlags(flags) == MONOMORPHIC);
00068 ASSERT(Code::kFlagsICStateShift == 0);
00069
00070
00071 ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
00072
00073
00074 int primary_offset = PrimaryOffset(name, flags, map);
00075 Entry* primary = entry(primary_, primary_offset);
00076 Code* hit = primary->value;
00077
00078
00079
00080 if (hit != Builtins::builtin(Builtins::Illegal)) {
00081 Code::Flags primary_flags = Code::RemoveTypeFromFlags(hit->flags());
00082 int secondary_offset =
00083 SecondaryOffset(primary->key, primary_flags, primary_offset);
00084 Entry* secondary = entry(secondary_, secondary_offset);
00085 *secondary = *primary;
00086 }
00087
00088
00089 primary->key = name;
00090 primary->value = code;
00091 return code;
00092 }
00093
00094
00095 Object* StubCache::ComputeLoadField(String* name,
00096 JSObject* receiver,
00097 JSObject* holder,
00098 int field_index) {
00099 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, FIELD);
00100 Object* code = receiver->map()->FindInCodeCache(name, flags);
00101 if (code->IsUndefined()) {
00102 LoadStubCompiler compiler;
00103 code = compiler.CompileLoadField(receiver, holder, field_index);
00104 if (code->IsFailure()) return code;
00105 LOG(CodeCreateEvent("LoadIC", Code::cast(code), name));
00106 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
00107 if (result->IsFailure()) return code;
00108 }
00109 return Set(name, receiver->map(), Code::cast(code));
00110 }
00111
00112
00113 Object* StubCache::ComputeLoadCallback(String* name,
00114 JSObject* receiver,
00115 JSObject* holder,
00116 AccessorInfo* callback) {
00117 ASSERT(v8::ToCData<Address>(callback->getter()) != 0);
00118 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, CALLBACKS);
00119 Object* code = receiver->map()->FindInCodeCache(name, flags);
00120 if (code->IsUndefined()) {
00121 LoadStubCompiler compiler;
00122 code = compiler.CompileLoadCallback(receiver, holder, callback);
00123 if (code->IsFailure()) return code;
00124 LOG(CodeCreateEvent("LoadIC", Code::cast(code), name));
00125 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
00126 if (result->IsFailure()) return code;
00127 }
00128 return Set(name, receiver->map(), Code::cast(code));
00129 }
00130
00131
00132 Object* StubCache::ComputeLoadConstant(String* name,
00133 JSObject* receiver,
00134 JSObject* holder,
00135 Object* value) {
00136 Code::Flags flags =
00137 Code::ComputeMonomorphicFlags(Code::LOAD_IC, CONSTANT_FUNCTION);
00138 Object* code = receiver->map()->FindInCodeCache(name, flags);
00139 if (code->IsUndefined()) {
00140 LoadStubCompiler compiler;
00141 code = compiler.CompileLoadConstant(receiver, holder, value);
00142 if (code->IsFailure()) return code;
00143 LOG(CodeCreateEvent("LoadIC", Code::cast(code), name));
00144 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
00145 if (result->IsFailure()) return code;
00146 }
00147 return Set(name, receiver->map(), Code::cast(code));
00148 }
00149
00150
00151 Object* StubCache::ComputeLoadInterceptor(String* name,
00152 JSObject* receiver,
00153 JSObject* holder) {
00154 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, INTERCEPTOR);
00155 Object* code = receiver->map()->FindInCodeCache(name, flags);
00156 if (code->IsUndefined()) {
00157 LoadStubCompiler compiler;
00158 code = compiler.CompileLoadInterceptor(receiver, holder, name);
00159 if (code->IsFailure()) return code;
00160 LOG(CodeCreateEvent("LoadIC", Code::cast(code), name));
00161 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
00162 if (result->IsFailure()) return code;
00163 }
00164 return Set(name, receiver->map(), Code::cast(code));
00165 }
00166
00167
00168 Object* StubCache::ComputeLoadNormal(String* name, JSObject* receiver) {
00169 Code* code = Builtins::builtin(Builtins::LoadIC_Normal);
00170 return Set(name, receiver->map(), code);
00171 }
00172
00173
00174 Object* StubCache::ComputeKeyedLoadField(String* name,
00175 JSObject* receiver,
00176 JSObject* holder,
00177 int field_index) {
00178 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, FIELD);
00179 Object* code = receiver->map()->FindInCodeCache(name, flags);
00180 if (code->IsUndefined()) {
00181 KeyedLoadStubCompiler compiler;
00182 code = compiler.CompileLoadField(name, receiver, holder, field_index);
00183 if (code->IsFailure()) return code;
00184 LOG(CodeCreateEvent("KeyedLoadIC", Code::cast(code), name));
00185 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
00186 if (result->IsFailure()) return result;
00187 }
00188 return code;
00189 }
00190
00191
00192 Object* StubCache::ComputeKeyedLoadConstant(String* name,
00193 JSObject* receiver,
00194 JSObject* holder,
00195 Object* value) {
00196 Code::Flags flags =
00197 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CONSTANT_FUNCTION);
00198 Object* code = receiver->map()->FindInCodeCache(name, flags);
00199 if (code->IsUndefined()) {
00200 KeyedLoadStubCompiler compiler;
00201 code = compiler.CompileLoadConstant(name, receiver, holder, value);
00202 if (code->IsFailure()) return code;
00203 LOG(CodeCreateEvent("KeyedLoadIC", Code::cast(code), name));
00204 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
00205 if (result->IsFailure()) return result;
00206 }
00207 return code;
00208 }
00209
00210
00211 Object* StubCache::ComputeKeyedLoadInterceptor(String* name,
00212 JSObject* receiver,
00213 JSObject* holder) {
00214 Code::Flags flags =
00215 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, INTERCEPTOR);
00216 Object* code = receiver->map()->FindInCodeCache(name, flags);
00217 if (code->IsUndefined()) {
00218 KeyedLoadStubCompiler compiler;
00219 code = compiler.CompileLoadInterceptor(receiver, holder, name);
00220 if (code->IsFailure()) return code;
00221 LOG(CodeCreateEvent("KeyedLoadIC", Code::cast(code), name));
00222 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
00223 if (result->IsFailure()) return result;
00224 }
00225 return code;
00226 }
00227
00228
00229 Object* StubCache::ComputeKeyedLoadCallback(String* name,
00230 JSObject* receiver,
00231 JSObject* holder,
00232 AccessorInfo* callback) {
00233 Code::Flags flags =
00234 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
00235 Object* code = receiver->map()->FindInCodeCache(name, flags);
00236 if (code->IsUndefined()) {
00237 KeyedLoadStubCompiler compiler;
00238 code = compiler.CompileLoadCallback(name, receiver, holder, callback);
00239 if (code->IsFailure()) return code;
00240 LOG(CodeCreateEvent("KeyedLoadIC", Code::cast(code), name));
00241 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
00242 if (result->IsFailure()) return result;
00243 }
00244 return code;
00245 }
00246
00247
00248
00249 Object* StubCache::ComputeKeyedLoadArrayLength(String* name,
00250 JSArray* receiver) {
00251 Code::Flags flags =
00252 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
00253 Object* code = receiver->map()->FindInCodeCache(name, flags);
00254 if (code->IsUndefined()) {
00255 KeyedLoadStubCompiler compiler;
00256 code = compiler.CompileLoadArrayLength(name);
00257 if (code->IsFailure()) return code;
00258 LOG(CodeCreateEvent("KeyedLoadIC", Code::cast(code), name));
00259 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
00260 if (result->IsFailure()) return result;
00261 }
00262 return code;
00263 }
00264
00265
00266 Object* StubCache::ComputeKeyedLoadStringLength(String* name,
00267 String* receiver) {
00268 Code::Flags flags =
00269 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
00270 Object* code = receiver->map()->FindInCodeCache(name, flags);
00271 if (code->IsUndefined()) {
00272 KeyedLoadStubCompiler compiler;
00273 code = compiler.CompileLoadStringLength(name);
00274 if (code->IsFailure()) return code;
00275 LOG(CodeCreateEvent("KeyedLoadIC", Code::cast(code), name));
00276 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
00277 if (result->IsFailure()) return result;
00278 }
00279 return code;
00280 }
00281
00282
00283 Object* StubCache::ComputeKeyedLoadFunctionPrototype(String* name,
00284 JSFunction* receiver) {
00285 Code::Flags flags =
00286 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
00287 Object* code = receiver->map()->FindInCodeCache(name, flags);
00288 if (code->IsUndefined()) {
00289 KeyedLoadStubCompiler compiler;
00290 code = compiler.CompileLoadFunctionPrototype(name);
00291 if (code->IsFailure()) return code;
00292 LOG(CodeCreateEvent("KeyedLoadIC", Code::cast(code), name));
00293 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
00294 if (result->IsFailure()) return result;
00295 }
00296 return code;
00297 }
00298
00299
00300 Object* StubCache::ComputeStoreField(String* name,
00301 JSObject* receiver,
00302 int field_index,
00303 Map* transition) {
00304 PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION;
00305 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, type);
00306 Object* code = receiver->map()->FindInCodeCache(name, flags);
00307 if (code->IsUndefined()) {
00308 StoreStubCompiler compiler;
00309 code = compiler.CompileStoreField(receiver, field_index, transition, name);
00310 if (code->IsFailure()) return code;
00311 LOG(CodeCreateEvent("StoreIC", Code::cast(code), name));
00312 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
00313 if (result->IsFailure()) return result;
00314 }
00315 return Set(name, receiver->map(), Code::cast(code));
00316 }
00317
00318
00319 Object* StubCache::ComputeStoreCallback(String* name,
00320 JSObject* receiver,
00321 AccessorInfo* callback) {
00322 ASSERT(v8::ToCData<Address>(callback->setter()) != 0);
00323 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, CALLBACKS);
00324 Object* code = receiver->map()->FindInCodeCache(name, flags);
00325 if (code->IsUndefined()) {
00326 StoreStubCompiler compiler;
00327 code = compiler.CompileStoreCallback(receiver, callback, name);
00328 if (code->IsFailure()) return code;
00329 LOG(CodeCreateEvent("StoreIC", Code::cast(code), name));
00330 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
00331 if (result->IsFailure()) return result;
00332 }
00333 return Set(name, receiver->map(), Code::cast(code));
00334 }
00335
00336
00337 Object* StubCache::ComputeStoreInterceptor(String* name,
00338 JSObject* receiver) {
00339 Code::Flags flags =
00340 Code::ComputeMonomorphicFlags(Code::STORE_IC, INTERCEPTOR);
00341 Object* code = receiver->map()->FindInCodeCache(name, flags);
00342 if (code->IsUndefined()) {
00343 StoreStubCompiler compiler;
00344 code = compiler.CompileStoreInterceptor(receiver, name);
00345 if (code->IsFailure()) return code;
00346 LOG(CodeCreateEvent("StoreIC", Code::cast(code), name));
00347 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
00348 if (result->IsFailure()) return result;
00349 }
00350 return Set(name, receiver->map(), Code::cast(code));
00351 }
00352
00353
00354 Object* StubCache::ComputeKeyedStoreField(String* name, JSObject* receiver,
00355 int field_index, Map* transition) {
00356 PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION;
00357 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, type);
00358 Object* code = receiver->map()->FindInCodeCache(name, flags);
00359 if (code->IsUndefined()) {
00360 KeyedStoreStubCompiler compiler;
00361 code = compiler.CompileStoreField(receiver, field_index, transition, name);
00362 if (code->IsFailure()) return code;
00363 LOG(CodeCreateEvent("KeyedStoreIC", Code::cast(code), name));
00364 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
00365 if (result->IsFailure()) return result;
00366 }
00367 return code;
00368 }
00369
00370
00371 Object* StubCache::ComputeCallConstant(int argc,
00372 String* name,
00373 Object* object,
00374 JSObject* holder,
00375 JSFunction* function) {
00376
00377 Map* map = IC::GetCodeCacheMapForObject(object);
00378
00379
00380 StubCompiler::CheckType check = StubCompiler::RECEIVER_MAP_CHECK;
00381 if (object->IsString()) {
00382 check = StubCompiler::STRING_CHECK;
00383 } else if (object->IsNumber()) {
00384 check = StubCompiler::NUMBER_CHECK;
00385 } else if (object->IsBoolean()) {
00386 check = StubCompiler::BOOLEAN_CHECK;
00387 }
00388
00389 Code::Flags flags =
00390 Code::ComputeMonomorphicFlags(Code::CALL_IC, CONSTANT_FUNCTION, argc);
00391 Object* code = map->FindInCodeCache(name, flags);
00392 if (code->IsUndefined()) {
00393 if (object->IsJSObject()) {
00394 Object* opt =
00395 Top::LookupSpecialFunction(JSObject::cast(object), holder, function);
00396 if (opt->IsJSFunction()) {
00397 check = StubCompiler::JSARRAY_HAS_FAST_ELEMENTS_CHECK;
00398 function = JSFunction::cast(opt);
00399 }
00400 }
00401
00402
00403
00404
00405 if (!function->is_compiled()) return Failure::InternalError();
00406
00407 CallStubCompiler compiler(argc);
00408 code = compiler.CompileCallConstant(object, holder, function, check);
00409 if (code->IsFailure()) return code;
00410 LOG(CodeCreateEvent("CallIC", Code::cast(code), name));
00411 Object* result = map->UpdateCodeCache(name, Code::cast(code));
00412 if (result->IsFailure()) return result;
00413 }
00414 return Set(name, map, Code::cast(code));
00415 }
00416
00417
00418 Object* StubCache::ComputeCallField(int argc,
00419 String* name,
00420 Object* object,
00421 JSObject* holder,
00422 int index) {
00423
00424 Map* map = IC::GetCodeCacheMapForObject(object);
00425
00426
00427
00428
00429 if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
00430 object = holder;
00431 }
00432
00433 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC, FIELD, argc);
00434 Object* code = map->FindInCodeCache(name, flags);
00435 if (code->IsUndefined()) {
00436 CallStubCompiler compiler(argc);
00437 code = compiler.CompileCallField(object, holder, index);
00438 if (code->IsFailure()) return code;
00439 LOG(CodeCreateEvent("CallIC", Code::cast(code), name));
00440 Object* result = map->UpdateCodeCache(name, Code::cast(code));
00441 if (result->IsFailure()) return result;
00442 }
00443 return Set(name, map, Code::cast(code));
00444 }
00445
00446
00447 Object* StubCache::ComputeCallInterceptor(int argc,
00448 String* name,
00449 Object* object,
00450 JSObject* holder) {
00451
00452
00453 Map* map = IC::GetCodeCacheMapForObject(object);
00454
00455
00456
00457
00458 if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
00459 object = holder;
00460 }
00461
00462 Code::Flags flags =
00463 Code::ComputeMonomorphicFlags(Code::CALL_IC, INTERCEPTOR, argc);
00464 Object* code = map->FindInCodeCache(name, flags);
00465 if (code->IsUndefined()) {
00466 CallStubCompiler compiler(argc);
00467 code = compiler.CompileCallInterceptor(object, holder, name);
00468 if (code->IsFailure()) return code;
00469 LOG(CodeCreateEvent("CallIC", Code::cast(code), name));
00470 Object* result = map->UpdateCodeCache(name, Code::cast(code));
00471 if (result->IsFailure()) return result;
00472 }
00473 return Set(name, map, Code::cast(code));
00474 }
00475
00476
00477 Object* StubCache::ComputeCallNormal(int argc,
00478 String* name,
00479 JSObject* receiver) {
00480 Object* code = ComputeCallNormal(argc);
00481 if (code->IsFailure()) return code;
00482 return Set(name, receiver->map(), Code::cast(code));
00483 }
00484
00485
00486 static Object* GetProbeValue(Code::Flags flags) {
00487 Dictionary* dictionary = Heap::non_monomorphic_cache();
00488 int entry = dictionary->FindNumberEntry(flags);
00489 if (entry != -1) return dictionary->ValueAt(entry);
00490 return Heap::undefined_value();
00491 }
00492
00493
00494 static Object* ProbeCache(Code::Flags flags) {
00495 Object* probe = GetProbeValue(flags);
00496 if (probe != Heap::undefined_value()) return probe;
00497
00498
00499
00500 Object* result =
00501 Heap::non_monomorphic_cache()->AtNumberPut(flags,
00502 Heap::undefined_value());
00503 if (result->IsFailure()) return result;
00504 Heap::set_non_monomorphic_cache(Dictionary::cast(result));
00505 return probe;
00506 }
00507
00508
00509 static Object* FillCache(Object* code) {
00510 if (code->IsCode()) {
00511 int entry =
00512 Heap::non_monomorphic_cache()->FindNumberEntry(
00513 Code::cast(code)->flags());
00514
00515 ASSERT(entry != -1);
00516 ASSERT(Heap::non_monomorphic_cache()->ValueAt(entry) ==
00517 Heap::undefined_value());
00518 Heap::non_monomorphic_cache()->ValueAtPut(entry, code);
00519 CHECK(GetProbeValue(Code::cast(code)->flags()) == code);
00520 }
00521 return code;
00522 }
00523
00524
00525 Code* StubCache::FindCallInitialize(int argc) {
00526 Code::Flags flags =
00527 Code::ComputeFlags(Code::CALL_IC, UNINITIALIZED, NORMAL, argc);
00528 Object* result = ProbeCache(flags);
00529 ASSERT(!result->IsUndefined());
00530
00531
00532 return reinterpret_cast<Code*>(result);
00533 }
00534
00535
00536 Object* StubCache::ComputeCallInitialize(int argc) {
00537 Code::Flags flags =
00538 Code::ComputeFlags(Code::CALL_IC, UNINITIALIZED, NORMAL, argc);
00539 Object* probe = ProbeCache(flags);
00540 if (!probe->IsUndefined()) return probe;
00541 StubCompiler compiler;
00542 return FillCache(compiler.CompileCallInitialize(flags));
00543 }
00544
00545
00546 Object* StubCache::ComputeCallPreMonomorphic(int argc) {
00547 Code::Flags flags =
00548 Code::ComputeFlags(Code::CALL_IC, PREMONOMORPHIC, NORMAL, argc);
00549 Object* probe = ProbeCache(flags);
00550 if (!probe->IsUndefined()) return probe;
00551 StubCompiler compiler;
00552 return FillCache(compiler.CompileCallPreMonomorphic(flags));
00553 }
00554
00555
00556 Object* StubCache::ComputeCallNormal(int argc) {
00557 Code::Flags flags =
00558 Code::ComputeFlags(Code::CALL_IC, MONOMORPHIC, NORMAL, argc);
00559 Object* probe = ProbeCache(flags);
00560 if (!probe->IsUndefined()) return probe;
00561 StubCompiler compiler;
00562 return FillCache(compiler.CompileCallNormal(flags));
00563 }
00564
00565
00566 Object* StubCache::ComputeCallMegamorphic(int argc) {
00567 Code::Flags flags =
00568 Code::ComputeFlags(Code::CALL_IC, MEGAMORPHIC, NORMAL, argc);
00569 Object* probe = ProbeCache(flags);
00570 if (!probe->IsUndefined()) return probe;
00571 StubCompiler compiler;
00572 return FillCache(compiler.CompileCallMegamorphic(flags));
00573 }
00574
00575
00576 Object* StubCache::ComputeCallMiss(int argc) {
00577 Code::Flags flags =
00578 Code::ComputeFlags(Code::STUB, MEGAMORPHIC, NORMAL, argc);
00579 Object* probe = ProbeCache(flags);
00580 if (!probe->IsUndefined()) return probe;
00581 StubCompiler compiler;
00582 return FillCache(compiler.CompileCallMiss(flags));
00583 }
00584
00585
00586 Object* StubCache::ComputeCallDebugBreak(int argc) {
00587 Code::Flags flags =
00588 Code::ComputeFlags(Code::CALL_IC, DEBUG_BREAK, NORMAL, argc);
00589 Object* probe = ProbeCache(flags);
00590 if (!probe->IsUndefined()) return probe;
00591 StubCompiler compiler;
00592 return FillCache(compiler.CompileCallDebugBreak(flags));
00593 }
00594
00595
00596 Object* StubCache::ComputeCallDebugPrepareStepIn(int argc) {
00597 Code::Flags flags =
00598 Code::ComputeFlags(Code::CALL_IC, DEBUG_PREPARE_STEP_IN, NORMAL, argc);
00599 Object* probe = ProbeCache(flags);
00600 if (!probe->IsUndefined()) return probe;
00601 StubCompiler compiler;
00602 return FillCache(compiler.CompileCallDebugPrepareStepIn(flags));
00603 }
00604
00605
00606 Object* StubCache::ComputeLazyCompile(int argc) {
00607 Code::Flags flags =
00608 Code::ComputeFlags(Code::STUB, UNINITIALIZED, NORMAL, argc);
00609 Object* probe = ProbeCache(flags);
00610 if (!probe->IsUndefined()) return probe;
00611 StubCompiler compiler;
00612 Object* result = FillCache(compiler.CompileLazyCompile(flags));
00613 if (result->IsCode()) {
00614 Code* code = Code::cast(result);
00615 USE(code);
00616 LOG(CodeCreateEvent("LazyCompile", code, code->arguments_count()));
00617 }
00618 return result;
00619 }
00620
00621
00622 void StubCache::Clear() {
00623 for (int i = 0; i < kPrimaryTableSize; i++) {
00624 primary_[i].key = Heap::empty_string();
00625 primary_[i].value = Builtins::builtin(Builtins::Illegal);
00626 }
00627 for (int j = 0; j < kSecondaryTableSize; j++) {
00628 secondary_[j].key = Heap::empty_string();
00629 secondary_[j].value = Builtins::builtin(Builtins::Illegal);
00630 }
00631 }
00632
00633
00634
00635
00636
00637
00638
00639 Handle<Code> ComputeCallMiss(int argc) {
00640 CALL_HEAP_FUNCTION(StubCache::ComputeCallMiss(argc), Code);
00641 }
00642
00643
00644
00645 Object* LoadCallbackProperty(Arguments args) {
00646 Handle<JSObject> recv = args.at<JSObject>(0);
00647 AccessorInfo* callback = AccessorInfo::cast(args[1]);
00648 v8::AccessorGetter fun =
00649 FUNCTION_CAST<v8::AccessorGetter>(
00650 v8::ToCData<Address>(callback->getter()));
00651 ASSERT(fun != NULL);
00652 Handle<String> name = args.at<String>(2);
00653 Handle<JSObject> holder = args.at<JSObject>(3);
00654 HandleScope scope;
00655 Handle<Object> data(callback->data());
00656 LOG(ApiNamedPropertyAccess("load", *recv, *name));
00657
00658
00659
00660
00661 v8::AccessorInfo info(
00662 v8::Utils::ToLocal(recv),
00663 v8::Utils::ToLocal(data),
00664 v8::Utils::ToLocal(holder));
00665 v8::Handle<v8::Value> result;
00666 {
00667
00668 VMState state(OTHER);
00669 result = fun(v8::Utils::ToLocal(name), info);
00670 }
00671 RETURN_IF_SCHEDULED_EXCEPTION();
00672 if (result.IsEmpty()) {
00673 return Heap::undefined_value();
00674 } else {
00675 return *v8::Utils::OpenHandle(*result);
00676 }
00677 }
00678
00679
00680 Object* StoreCallbackProperty(Arguments args) {
00681 Handle<JSObject> recv = args.at<JSObject>(0);
00682 AccessorInfo* callback = AccessorInfo::cast(args[1]);
00683 v8::AccessorSetter fun =
00684 FUNCTION_CAST<v8::AccessorSetter>(
00685 v8::ToCData<Address>(callback->setter()));
00686 ASSERT(fun != NULL);
00687 Handle<String> name = args.at<String>(2);
00688 Handle<Object> value = args.at<Object>(3);
00689 HandleScope scope;
00690 Handle<Object> data(callback->data());
00691 LOG(ApiNamedPropertyAccess("store", *recv, *name));
00692 v8::AccessorInfo info(
00693 v8::Utils::ToLocal(recv),
00694 v8::Utils::ToLocal(data),
00695 v8::Utils::ToLocal(recv));
00696 {
00697
00698 VMState state(OTHER);
00699 fun(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
00700 }
00701 RETURN_IF_SCHEDULED_EXCEPTION();
00702 return *value;
00703 }
00704
00705
00706 Object* LoadInterceptorProperty(Arguments args) {
00707 HandleScope scope;
00708 Handle<JSObject> recv = args.at<JSObject>(0);
00709 Handle<JSObject> holder = args.at<JSObject>(1);
00710 Handle<String> name = args.at<String>(2);
00711 ASSERT(holder->HasNamedInterceptor());
00712 PropertyAttributes attr = NONE;
00713 Handle<Object> result = GetPropertyWithInterceptor(recv, holder, name, &attr);
00714
00715
00716
00717
00718
00719 if (result.is_null()) {
00720
00721
00722
00723 ASSERT(Top::has_pending_exception());
00724 return Failure::Exception();
00725 }
00726
00727
00728 if (attr != ABSENT) return *result;
00729
00730
00731
00732
00733
00734 StackFrameIterator it;
00735 it.Advance();
00736 if (it.frame()->is_internal()) return *result;
00737
00738
00739
00740
00741 IC ic(IC::NO_EXTRA_FRAME);
00742 ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
00743 if (!ic.is_contextual()) return *result;
00744
00745
00746 Handle<Object> error =
00747 Factory::NewReferenceError("not_defined", HandleVector(&name, 1));
00748 return Top::Throw(*error);
00749 }
00750
00751
00752 Object* StoreInterceptorProperty(Arguments args) {
00753 HandleScope scope;
00754 Handle<JSObject> recv = args.at<JSObject>(0);
00755 Handle<String> name = args.at<String>(1);
00756 Handle<Object> value = args.at<Object>(2);
00757 ASSERT(recv->HasNamedInterceptor());
00758 PropertyAttributes attr = NONE;
00759 Handle<Object> result = SetPropertyWithInterceptor(recv, name, value, attr);
00760
00761
00762
00763
00764
00765 if (result.is_null()) {
00766
00767
00768
00769 ASSERT(Top::has_pending_exception());
00770 return Failure::Exception();
00771 }
00772 return *result;
00773 }
00774
00775
00776 Object* StubCompiler::CompileCallInitialize(Code::Flags flags) {
00777 HandleScope scope;
00778 int argc = Code::ExtractArgumentsCountFromFlags(flags);
00779 CallIC::GenerateInitialize(masm(), argc);
00780 Object* result = GetCodeWithFlags(flags);
00781 if (!result->IsFailure()) {
00782 Counters::call_initialize_stubs.Increment();
00783 Code* code = Code::cast(result);
00784 USE(code);
00785 LOG(CodeCreateEvent("CallInitialize", code, code->arguments_count()));
00786 }
00787 return result;
00788 }
00789
00790
00791 Object* StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
00792 HandleScope scope;
00793 int argc = Code::ExtractArgumentsCountFromFlags(flags);
00794 CallIC::GenerateInitialize(masm(), argc);
00795 Object* result = GetCodeWithFlags(flags);
00796 if (!result->IsFailure()) {
00797 Counters::call_premonomorphic_stubs.Increment();
00798 Code* code = Code::cast(result);
00799 USE(code);
00800 LOG(CodeCreateEvent("CallPreMonomorphic", code, code->arguments_count()));
00801 }
00802 return result;
00803 }
00804
00805
00806 Object* StubCompiler::CompileCallNormal(Code::Flags flags) {
00807 HandleScope scope;
00808 int argc = Code::ExtractArgumentsCountFromFlags(flags);
00809 CallIC::GenerateNormal(masm(), argc);
00810 Object* result = GetCodeWithFlags(flags);
00811 if (!result->IsFailure()) {
00812 Counters::call_normal_stubs.Increment();
00813 Code* code = Code::cast(result);
00814 USE(code);
00815 LOG(CodeCreateEvent("CallNormal", code, code->arguments_count()));
00816 }
00817 return result;
00818 }
00819
00820
00821 Object* StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
00822 HandleScope scope;
00823 int argc = Code::ExtractArgumentsCountFromFlags(flags);
00824 CallIC::GenerateMegamorphic(masm(), argc);
00825 Object* result = GetCodeWithFlags(flags);
00826 if (!result->IsFailure()) {
00827 Counters::call_megamorphic_stubs.Increment();
00828 Code* code = Code::cast(result);
00829 USE(code);
00830 LOG(CodeCreateEvent("CallMegamorphic", code, code->arguments_count()));
00831 }
00832 return result;
00833 }
00834
00835
00836 Object* StubCompiler::CompileCallMiss(Code::Flags flags) {
00837 HandleScope scope;
00838 int argc = Code::ExtractArgumentsCountFromFlags(flags);
00839 CallIC::GenerateMiss(masm(), argc);
00840 Object* result = GetCodeWithFlags(flags);
00841 if (!result->IsFailure()) {
00842 Counters::call_megamorphic_stubs.Increment();
00843 Code* code = Code::cast(result);
00844 USE(code);
00845 LOG(CodeCreateEvent("CallMiss", code, code->arguments_count()));
00846 }
00847 return result;
00848 }
00849
00850
00851 Object* StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
00852 HandleScope scope;
00853 Builtins::Generate_CallIC_DebugBreak(masm());
00854 Object* result = GetCodeWithFlags(flags);
00855 if (!result->IsFailure()) {
00856 Code* code = Code::cast(result);
00857 USE(code);
00858 LOG(CodeCreateEvent("CallDebugBreak", code, code->arguments_count()));
00859 }
00860 return result;
00861 }
00862
00863
00864 Object* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
00865 HandleScope scope;
00866
00867
00868 int argc = Code::ExtractArgumentsCountFromFlags(flags);
00869 CallIC::GenerateMiss(masm(), argc);
00870 Object* result = GetCodeWithFlags(flags);
00871 if (!result->IsFailure()) {
00872 Code* code = Code::cast(result);
00873 USE(code);
00874 LOG(CodeCreateEvent("CallDebugPrepareStepIn", code,
00875 code->arguments_count()));
00876 }
00877 return result;
00878 }
00879
00880
00881 Object* StubCompiler::GetCodeWithFlags(Code::Flags flags) {
00882 CodeDesc desc;
00883 masm_.GetCode(&desc);
00884 Object* result = Heap::CreateCode(desc, NULL, flags);
00885 #ifdef DEBUG
00886 if (FLAG_print_code_stubs && !result->IsFailure()) {
00887 Code::cast(result)->Print();
00888 }
00889 #endif
00890 return result;
00891 }
00892
00893
00894 Object* LoadStubCompiler::GetCode(PropertyType type) {
00895 return GetCodeWithFlags(Code::ComputeMonomorphicFlags(Code::LOAD_IC, type));
00896 }
00897
00898
00899 Object* KeyedLoadStubCompiler::GetCode(PropertyType type) {
00900 return GetCodeWithFlags(Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC,
00901 type));
00902 }
00903
00904
00905 Object* StoreStubCompiler::GetCode(PropertyType type) {
00906 return GetCodeWithFlags(Code::ComputeMonomorphicFlags(Code::STORE_IC, type));
00907 }
00908
00909
00910 Object* KeyedStoreStubCompiler::GetCode(PropertyType type) {
00911 return GetCodeWithFlags(Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC,
00912 type));
00913 }
00914
00915
00916 Object* CallStubCompiler::GetCode(PropertyType type) {
00917 int argc = arguments_.immediate();
00918 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC, type, argc);
00919 return GetCodeWithFlags(flags);
00920 }
00921
00922
00923 } }