| OLD | NEW | 
|---|
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without | 
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are | 
| 4 // met: | 4 // met: | 
| 5 // | 5 // | 
| 6 //     * Redistributions of source code must retain the above copyright | 6 //     * Redistributions of source code must retain the above copyright | 
| 7 //       notice, this list of conditions and the following disclaimer. | 7 //       notice, this list of conditions and the following disclaimer. | 
| 8 //     * Redistributions in binary form must reproduce the above | 8 //     * Redistributions in binary form must reproduce the above | 
| 9 //       copyright notice, this list of conditions and the following | 9 //       copyright notice, this list of conditions and the following | 
| 10 //       disclaimer in the documentation and/or other materials provided | 10 //       disclaimer in the documentation and/or other materials provided | 
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 58   return 0; | 58   return 0; | 
| 59 } | 59 } | 
| 60 | 60 | 
| 61 void IC::TraceIC(const char* type, | 61 void IC::TraceIC(const char* type, | 
| 62                  Handle<Object> name, | 62                  Handle<Object> name, | 
| 63                  State old_state, | 63                  State old_state, | 
| 64                  Code* new_target, | 64                  Code* new_target, | 
| 65                  const char* extra_info) { | 65                  const char* extra_info) { | 
| 66   if (FLAG_trace_ic) { | 66   if (FLAG_trace_ic) { | 
| 67     State new_state = StateFrom(new_target, | 67     State new_state = StateFrom(new_target, | 
| 68                                 Heap::undefined_value(), | 68                                 HEAP->undefined_value(), | 
| 69                                 Heap::undefined_value()); | 69                                 HEAP->undefined_value()); | 
| 70     PrintF("[%s (%c->%c)%s", type, | 70     PrintF("[%s (%c->%c)%s", type, | 
| 71            TransitionMarkFromState(old_state), | 71            TransitionMarkFromState(old_state), | 
| 72            TransitionMarkFromState(new_state), | 72            TransitionMarkFromState(new_state), | 
| 73            extra_info); | 73            extra_info); | 
| 74     name->Print(); | 74     name->Print(); | 
| 75     PrintF("]\n"); | 75     PrintF("]\n"); | 
| 76   } | 76   } | 
| 77 } | 77 } | 
| 78 #endif | 78 #endif | 
| 79 | 79 | 
| 80 | 80 | 
| 81 IC::IC(FrameDepth depth) { | 81 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) { | 
|  | 82   ASSERT(isolate == Isolate::Current()); | 
| 82   // To improve the performance of the (much used) IC code, we unfold | 83   // To improve the performance of the (much used) IC code, we unfold | 
| 83   // a few levels of the stack frame iteration code. This yields a | 84   // a few levels of the stack frame iteration code. This yields a | 
| 84   // ~35% speedup when running DeltaBlue with the '--nouse-ic' flag. | 85   // ~35% speedup when running DeltaBlue with the '--nouse-ic' flag. | 
| 85   const Address entry = Top::c_entry_fp(Top::GetCurrentThread()); | 86   const Address entry = | 
|  | 87       Isolate::c_entry_fp(isolate->thread_local_top()); | 
| 86   Address* pc_address = | 88   Address* pc_address = | 
| 87       reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset); | 89       reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset); | 
| 88   Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); | 90   Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); | 
| 89   // If there's another JavaScript frame on the stack, we need to look | 91   // If there's another JavaScript frame on the stack, we need to look | 
| 90   // one frame further down the stack to find the frame pointer and | 92   // one frame further down the stack to find the frame pointer and | 
| 91   // the return address stack slot. | 93   // the return address stack slot. | 
| 92   if (depth == EXTRA_CALL_FRAME) { | 94   if (depth == EXTRA_CALL_FRAME) { | 
| 93     const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset; | 95     const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset; | 
| 94     pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset); | 96     pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset); | 
| 95     fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset); | 97     fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset); | 
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 129   // Return the address in the original code. This is the place where | 131   // Return the address in the original code. This is the place where | 
| 130   // the call which has been overwritten by the DebugBreakXXX resides | 132   // the call which has been overwritten by the DebugBreakXXX resides | 
| 131   // and the place where the inline cache system should look. | 133   // and the place where the inline cache system should look. | 
| 132   intptr_t delta = | 134   intptr_t delta = | 
| 133       original_code->instruction_start() - code->instruction_start(); | 135       original_code->instruction_start() - code->instruction_start(); | 
| 134   return addr + delta; | 136   return addr + delta; | 
| 135 } | 137 } | 
| 136 #endif | 138 #endif | 
| 137 | 139 | 
| 138 | 140 | 
| 139 static bool HasNormalObjectsInPrototypeChain(LookupResult* lookup, | 141 static bool HasNormalObjectsInPrototypeChain(Isolate* isolate, | 
|  | 142                                              LookupResult* lookup, | 
| 140                                              Object* receiver) { | 143                                              Object* receiver) { | 
| 141   Object* end = lookup->IsProperty() ? lookup->holder() : Heap::null_value(); | 144   Object* end = lookup->IsProperty() | 
|  | 145       ? lookup->holder() : isolate->heap()->null_value(); | 
| 142   for (Object* current = receiver; | 146   for (Object* current = receiver; | 
| 143        current != end; | 147        current != end; | 
| 144        current = current->GetPrototype()) { | 148        current = current->GetPrototype()) { | 
| 145     if (current->IsJSObject() && | 149     if (current->IsJSObject() && | 
| 146         !JSObject::cast(current)->HasFastProperties() && | 150         !JSObject::cast(current)->HasFastProperties() && | 
| 147         !current->IsJSGlobalProxy() && | 151         !current->IsJSGlobalProxy() && | 
| 148         !current->IsJSGlobalObject()) { | 152         !current->IsJSGlobalObject()) { | 
| 149       return true; | 153       return true; | 
| 150     } | 154     } | 
| 151   } | 155   } | 
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 224   if (receiver->IsJSBuiltinsObject()) { | 228   if (receiver->IsJSBuiltinsObject()) { | 
| 225     return UNINITIALIZED; | 229     return UNINITIALIZED; | 
| 226   } | 230   } | 
| 227 | 231 | 
| 228   return MONOMORPHIC; | 232   return MONOMORPHIC; | 
| 229 } | 233 } | 
| 230 | 234 | 
| 231 | 235 | 
| 232 RelocInfo::Mode IC::ComputeMode() { | 236 RelocInfo::Mode IC::ComputeMode() { | 
| 233   Address addr = address(); | 237   Address addr = address(); | 
| 234   Code* code = Code::cast(Heap::FindCodeObject(addr)); | 238   Code* code = Code::cast(isolate()->heap()->FindCodeObject(addr)); | 
| 235   for (RelocIterator it(code, RelocInfo::kCodeTargetMask); | 239   for (RelocIterator it(code, RelocInfo::kCodeTargetMask); | 
| 236        !it.done(); it.next()) { | 240        !it.done(); it.next()) { | 
| 237     RelocInfo* info = it.rinfo(); | 241     RelocInfo* info = it.rinfo(); | 
| 238     if (info->pc() == addr) return info->rmode(); | 242     if (info->pc() == addr) return info->rmode(); | 
| 239   } | 243   } | 
| 240   UNREACHABLE(); | 244   UNREACHABLE(); | 
| 241   return RelocInfo::NONE; | 245   return RelocInfo::NONE; | 
| 242 } | 246 } | 
| 243 | 247 | 
| 244 | 248 | 
| 245 Failure* IC::TypeError(const char* type, | 249 Failure* IC::TypeError(const char* type, | 
| 246                        Handle<Object> object, | 250                        Handle<Object> object, | 
| 247                        Handle<Object> key) { | 251                        Handle<Object> key) { | 
| 248   HandleScope scope; | 252   HandleScope scope(isolate()); | 
| 249   Handle<Object> args[2] = { key, object }; | 253   Handle<Object> args[2] = { key, object }; | 
| 250   Handle<Object> error = Factory::NewTypeError(type, HandleVector(args, 2)); | 254   Handle<Object> error = isolate()->factory()->NewTypeError( | 
| 251   return Top::Throw(*error); | 255       type, HandleVector(args, 2)); | 
|  | 256   return isolate()->Throw(*error); | 
| 252 } | 257 } | 
| 253 | 258 | 
| 254 | 259 | 
| 255 Failure* IC::ReferenceError(const char* type, Handle<String> name) { | 260 Failure* IC::ReferenceError(const char* type, Handle<String> name) { | 
| 256   HandleScope scope; | 261   HandleScope scope(isolate()); | 
| 257   Handle<Object> error = | 262   Handle<Object> error = isolate()->factory()->NewReferenceError( | 
| 258       Factory::NewReferenceError(type, HandleVector(&name, 1)); | 263       type, HandleVector(&name, 1)); | 
| 259   return Top::Throw(*error); | 264   return isolate()->Throw(*error); | 
| 260 } | 265 } | 
| 261 | 266 | 
| 262 | 267 | 
| 263 void IC::Clear(Address address) { | 268 void IC::Clear(Address address) { | 
| 264   Code* target = GetTargetAtAddress(address); | 269   Code* target = GetTargetAtAddress(address); | 
| 265 | 270 | 
| 266   // Don't clear debug break inline cache as it will remove the break point. | 271   // Don't clear debug break inline cache as it will remove the break point. | 
| 267   if (target->ic_state() == DEBUG_BREAK) return; | 272   if (target->ic_state() == DEBUG_BREAK) return; | 
| 268 | 273 | 
| 269   switch (target->kind()) { | 274   switch (target->kind()) { | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
| 285       return; | 290       return; | 
| 286     default: UNREACHABLE(); | 291     default: UNREACHABLE(); | 
| 287   } | 292   } | 
| 288 } | 293 } | 
| 289 | 294 | 
| 290 | 295 | 
| 291 void CallICBase::Clear(Address address, Code* target) { | 296 void CallICBase::Clear(Address address, Code* target) { | 
| 292   State state = target->ic_state(); | 297   State state = target->ic_state(); | 
| 293   if (state == UNINITIALIZED) return; | 298   if (state == UNINITIALIZED) return; | 
| 294   Code* code = | 299   Code* code = | 
| 295       StubCache::FindCallInitialize(target->arguments_count(), | 300       Isolate::Current()->stub_cache()->FindCallInitialize( | 
| 296                                     target->ic_in_loop(), | 301           target->arguments_count(), | 
| 297                                     target->kind()); | 302           target->ic_in_loop(), | 
|  | 303           target->kind()); | 
| 298   SetTargetAtAddress(address, code); | 304   SetTargetAtAddress(address, code); | 
| 299 } | 305 } | 
| 300 | 306 | 
| 301 | 307 | 
| 302 void KeyedLoadIC::ClearInlinedVersion(Address address) { | 308 void KeyedLoadIC::ClearInlinedVersion(Address address) { | 
| 303   // Insert null as the map to check for to make sure the map check fails | 309   // Insert null as the map to check for to make sure the map check fails | 
| 304   // sending control flow to the IC instead of the inlined version. | 310   // sending control flow to the IC instead of the inlined version. | 
| 305   PatchInlinedLoad(address, Heap::null_value()); | 311   PatchInlinedLoad(address, HEAP->null_value()); | 
| 306 } | 312 } | 
| 307 | 313 | 
| 308 | 314 | 
| 309 void KeyedLoadIC::Clear(Address address, Code* target) { | 315 void KeyedLoadIC::Clear(Address address, Code* target) { | 
| 310   if (target->ic_state() == UNINITIALIZED) return; | 316   if (target->ic_state() == UNINITIALIZED) return; | 
| 311   // Make sure to also clear the map used in inline fast cases.  If we | 317   // Make sure to also clear the map used in inline fast cases.  If we | 
| 312   // do not clear these maps, cached code can keep objects alive | 318   // do not clear these maps, cached code can keep objects alive | 
| 313   // through the embedded maps. | 319   // through the embedded maps. | 
| 314   ClearInlinedVersion(address); | 320   ClearInlinedVersion(address); | 
| 315   SetTargetAtAddress(address, initialize_stub()); | 321   SetTargetAtAddress(address, initialize_stub()); | 
| 316 } | 322 } | 
| 317 | 323 | 
| 318 | 324 | 
| 319 void LoadIC::ClearInlinedVersion(Address address) { | 325 void LoadIC::ClearInlinedVersion(Address address) { | 
| 320   // Reset the map check of the inlined inobject property load (if | 326   // Reset the map check of the inlined inobject property load (if | 
| 321   // present) to guarantee failure by holding an invalid map (the null | 327   // present) to guarantee failure by holding an invalid map (the null | 
| 322   // value).  The offset can be patched to anything. | 328   // value).  The offset can be patched to anything. | 
| 323   PatchInlinedLoad(address, Heap::null_value(), 0); | 329   Heap* heap = HEAP; | 
|  | 330   PatchInlinedLoad(address, heap->null_value(), 0); | 
| 324   PatchInlinedContextualLoad(address, | 331   PatchInlinedContextualLoad(address, | 
| 325                              Heap::null_value(), | 332                              heap->null_value(), | 
| 326                              Heap::null_value(), | 333                              heap->null_value(), | 
| 327                              true); | 334                              true); | 
| 328 } | 335 } | 
| 329 | 336 | 
| 330 | 337 | 
| 331 void LoadIC::Clear(Address address, Code* target) { | 338 void LoadIC::Clear(Address address, Code* target) { | 
| 332   if (target->ic_state() == UNINITIALIZED) return; | 339   if (target->ic_state() == UNINITIALIZED) return; | 
| 333   ClearInlinedVersion(address); | 340   ClearInlinedVersion(address); | 
| 334   SetTargetAtAddress(address, initialize_stub()); | 341   SetTargetAtAddress(address, initialize_stub()); | 
| 335 } | 342 } | 
| 336 | 343 | 
| 337 | 344 | 
| 338 void StoreIC::ClearInlinedVersion(Address address) { | 345 void StoreIC::ClearInlinedVersion(Address address) { | 
| 339   // Reset the map check of the inlined inobject property store (if | 346   // Reset the map check of the inlined inobject property store (if | 
| 340   // present) to guarantee failure by holding an invalid map (the null | 347   // present) to guarantee failure by holding an invalid map (the null | 
| 341   // value).  The offset can be patched to anything. | 348   // value).  The offset can be patched to anything. | 
| 342   PatchInlinedStore(address, Heap::null_value(), 0); | 349   PatchInlinedStore(address, HEAP->null_value(), 0); | 
| 343 } | 350 } | 
| 344 | 351 | 
| 345 | 352 | 
| 346 void StoreIC::Clear(Address address, Code* target) { | 353 void StoreIC::Clear(Address address, Code* target) { | 
| 347   if (target->ic_state() == UNINITIALIZED) return; | 354   if (target->ic_state() == UNINITIALIZED) return; | 
| 348   ClearInlinedVersion(address); | 355   ClearInlinedVersion(address); | 
| 349   SetTargetAtAddress(address, | 356   SetTargetAtAddress(address, | 
| 350       (target->extra_ic_state() == kStrictMode) | 357       (target->extra_ic_state() == kStrictMode) | 
| 351         ? initialize_stub_strict() | 358         ? initialize_stub_strict() | 
| 352         : initialize_stub()); | 359         : initialize_stub()); | 
| 353 } | 360 } | 
| 354 | 361 | 
| 355 | 362 | 
| 356 void KeyedStoreIC::ClearInlinedVersion(Address address) { | 363 void KeyedStoreIC::ClearInlinedVersion(Address address) { | 
| 357   // Insert null as the elements map to check for.  This will make | 364   // Insert null as the elements map to check for.  This will make | 
| 358   // sure that the elements fast-case map check fails so that control | 365   // sure that the elements fast-case map check fails so that control | 
| 359   // flows to the IC instead of the inlined version. | 366   // flows to the IC instead of the inlined version. | 
| 360   PatchInlinedStore(address, Heap::null_value()); | 367   PatchInlinedStore(address, HEAP->null_value()); | 
| 361 } | 368 } | 
| 362 | 369 | 
| 363 | 370 | 
| 364 void KeyedStoreIC::RestoreInlinedVersion(Address address) { | 371 void KeyedStoreIC::RestoreInlinedVersion(Address address) { | 
| 365   // Restore the fast-case elements map check so that the inlined | 372   // Restore the fast-case elements map check so that the inlined | 
| 366   // version can be used again. | 373   // version can be used again. | 
| 367   PatchInlinedStore(address, Heap::fixed_array_map()); | 374   PatchInlinedStore(address, HEAP->fixed_array_map()); | 
| 368 } | 375 } | 
| 369 | 376 | 
| 370 | 377 | 
| 371 void KeyedStoreIC::Clear(Address address, Code* target) { | 378 void KeyedStoreIC::Clear(Address address, Code* target) { | 
| 372   if (target->ic_state() == UNINITIALIZED) return; | 379   if (target->ic_state() == UNINITIALIZED) return; | 
| 373   SetTargetAtAddress(address, | 380   SetTargetAtAddress(address, | 
| 374       (target->extra_ic_state() == kStrictMode) | 381       (target->extra_ic_state() == kStrictMode) | 
| 375         ? initialize_stub_strict() | 382         ? initialize_stub_strict() | 
| 376         : initialize_stub()); | 383         : initialize_stub()); | 
| 377 } | 384 } | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 416       lookup->NotFound(); | 423       lookup->NotFound(); | 
| 417       return; | 424       return; | 
| 418     } | 425     } | 
| 419 | 426 | 
| 420     object = proto; | 427     object = proto; | 
| 421   } | 428   } | 
| 422 } | 429 } | 
| 423 | 430 | 
| 424 | 431 | 
| 425 Object* CallICBase::TryCallAsFunction(Object* object) { | 432 Object* CallICBase::TryCallAsFunction(Object* object) { | 
| 426   HandleScope scope; | 433   HandleScope scope(isolate()); | 
| 427   Handle<Object> target(object); | 434   Handle<Object> target(object, isolate()); | 
| 428   Handle<Object> delegate = Execution::GetFunctionDelegate(target); | 435   Handle<Object> delegate = Execution::GetFunctionDelegate(target); | 
| 429 | 436 | 
| 430   if (delegate->IsJSFunction()) { | 437   if (delegate->IsJSFunction()) { | 
| 431     // Patch the receiver and use the delegate as the function to | 438     // Patch the receiver and use the delegate as the function to | 
| 432     // invoke. This is used for invoking objects as if they were | 439     // invoke. This is used for invoking objects as if they were | 
| 433     // functions. | 440     // functions. | 
| 434     const int argc = this->target()->arguments_count(); | 441     const int argc = this->target()->arguments_count(); | 
| 435     StackFrameLocator locator; | 442     StackFrameLocator locator; | 
| 436     JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 443     JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 
| 437     int index = frame->ComputeExpressionsCount() - (argc + 1); | 444     int index = frame->ComputeExpressionsCount() - (argc + 1); | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
| 452     } | 459     } | 
| 453   } | 460   } | 
| 454 | 461 | 
| 455   // And only wrap string, number or boolean. | 462   // And only wrap string, number or boolean. | 
| 456   if (object->IsString() || object->IsNumber() || object->IsBoolean()) { | 463   if (object->IsString() || object->IsNumber() || object->IsBoolean()) { | 
| 457     // Change the receiver to the result of calling ToObject on it. | 464     // Change the receiver to the result of calling ToObject on it. | 
| 458     const int argc = this->target()->arguments_count(); | 465     const int argc = this->target()->arguments_count(); | 
| 459     StackFrameLocator locator; | 466     StackFrameLocator locator; | 
| 460     JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 467     JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 
| 461     int index = frame->ComputeExpressionsCount() - (argc + 1); | 468     int index = frame->ComputeExpressionsCount() - (argc + 1); | 
| 462     frame->SetExpression(index, *Factory::ToObject(object)); | 469     frame->SetExpression(index, *isolate()->factory()->ToObject(object)); | 
| 463   } | 470   } | 
| 464 } | 471 } | 
| 465 | 472 | 
| 466 | 473 | 
| 467 MaybeObject* CallICBase::LoadFunction(State state, | 474 MaybeObject* CallICBase::LoadFunction(State state, | 
| 468                                       Code::ExtraICState extra_ic_state, | 475                                       Code::ExtraICState extra_ic_state, | 
| 469                                       Handle<Object> object, | 476                                       Handle<Object> object, | 
| 470                                       Handle<String> name) { | 477                                       Handle<String> name) { | 
| 471   // If the object is undefined or null it's illegal to try to get any | 478   // If the object is undefined or null it's illegal to try to get any | 
| 472   // of its properties; throw a TypeError in that case. | 479   // of its properties; throw a TypeError in that case. | 
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 524     if (attr == ABSENT) { | 531     if (attr == ABSENT) { | 
| 525       if (IsContextual(object)) { | 532       if (IsContextual(object)) { | 
| 526         return ReferenceError("not_defined", name); | 533         return ReferenceError("not_defined", name); | 
| 527       } | 534       } | 
| 528       return TypeError("undefined_method", object, name); | 535       return TypeError("undefined_method", object, name); | 
| 529     } | 536     } | 
| 530   } | 537   } | 
| 531 | 538 | 
| 532   ASSERT(!result->IsTheHole()); | 539   ASSERT(!result->IsTheHole()); | 
| 533 | 540 | 
| 534   HandleScope scope; | 541   HandleScope scope(isolate()); | 
| 535   // Wrap result in a handle because ReceiverToObjectIfRequired may allocate | 542   // Wrap result in a handle because ReceiverToObjectIfRequired may allocate | 
| 536   // new object and cause GC. | 543   // new object and cause GC. | 
| 537   Handle<Object> result_handle(result); | 544   Handle<Object> result_handle(result); | 
| 538   // Make receiver an object if the callee requires it. Strict mode or builtin | 545   // Make receiver an object if the callee requires it. Strict mode or builtin | 
| 539   // functions do not wrap the receiver, non-strict functions and objects | 546   // functions do not wrap the receiver, non-strict functions and objects | 
| 540   // called as functions do. | 547   // called as functions do. | 
| 541   ReceiverToObjectIfRequired(result_handle, object); | 548   ReceiverToObjectIfRequired(result_handle, object); | 
| 542 | 549 | 
| 543   if (result_handle->IsJSFunction()) { | 550   if (result_handle->IsJSFunction()) { | 
| 544 #ifdef ENABLE_DEBUGGER_SUPPORT | 551 #ifdef ENABLE_DEBUGGER_SUPPORT | 
| 545     // Handle stepping into a function if step into is active. | 552     // Handle stepping into a function if step into is active. | 
| 546     if (Debug::StepInActive()) { | 553     Debug* debug = isolate()->debug(); | 
|  | 554     if (debug->StepInActive()) { | 
| 547       // Protect the result in a handle as the debugger can allocate and might | 555       // Protect the result in a handle as the debugger can allocate and might | 
| 548       // cause GC. | 556       // cause GC. | 
| 549       Handle<JSFunction> function(JSFunction::cast(*result_handle)); | 557       Handle<JSFunction> function(JSFunction::cast(*result_handle), isolate()); | 
| 550       Debug::HandleStepIn(function, object, fp(), false); | 558       debug->HandleStepIn(function, object, fp(), false); | 
| 551       return *function; | 559       return *function; | 
| 552     } | 560     } | 
| 553 #endif | 561 #endif | 
| 554 | 562 | 
| 555     return *result_handle; | 563     return *result_handle; | 
| 556   } | 564   } | 
| 557 | 565 | 
| 558   // Try to find a suitable function delegate for the object at hand. | 566   // Try to find a suitable function delegate for the object at hand. | 
| 559   result_handle = Handle<Object>(TryCallAsFunction(*result_handle)); | 567   result_handle = Handle<Object>(TryCallAsFunction(*result_handle)); | 
| 560   if (result_handle->IsJSFunction()) return *result_handle; | 568   if (result_handle->IsJSFunction()) return *result_handle; | 
| 561 | 569 | 
| 562   return TypeError("property_not_function", object, name); | 570   return TypeError("property_not_function", object, name); | 
| 563 } | 571 } | 
| 564 | 572 | 
| 565 | 573 | 
| 566 bool CallICBase::TryUpdateExtraICState(LookupResult* lookup, | 574 bool CallICBase::TryUpdateExtraICState(LookupResult* lookup, | 
| 567                                        Handle<Object> object, | 575                                        Handle<Object> object, | 
| 568                                        Code::ExtraICState* extra_ic_state) { | 576                                        Code::ExtraICState* extra_ic_state) { | 
| 569   ASSERT(kind_ == Code::CALL_IC); | 577   ASSERT(kind_ == Code::CALL_IC); | 
| 570   if (lookup->type() != CONSTANT_FUNCTION) return false; | 578   if (lookup->type() != CONSTANT_FUNCTION) return false; | 
| 571   JSFunction* function = lookup->GetConstantFunction(); | 579   JSFunction* function = lookup->GetConstantFunction(); | 
| 572   if (!function->shared()->HasBuiltinFunctionId()) return false; | 580   if (!function->shared()->HasBuiltinFunctionId()) return false; | 
| 573 | 581 | 
| 574   // Fetch the arguments passed to the called function. | 582   // Fetch the arguments passed to the called function. | 
| 575   const int argc = target()->arguments_count(); | 583   const int argc = target()->arguments_count(); | 
| 576   Address entry = Top::c_entry_fp(Top::GetCurrentThread()); | 584   Address entry = isolate()->c_entry_fp(isolate()->thread_local_top()); | 
| 577   Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); | 585   Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); | 
| 578   Arguments args(argc + 1, | 586   Arguments args(argc + 1, | 
| 579                  &Memory::Object_at(fp + | 587                  &Memory::Object_at(fp + | 
| 580                                     StandardFrameConstants::kCallerSPOffset + | 588                                     StandardFrameConstants::kCallerSPOffset + | 
| 581                                     argc * kPointerSize)); | 589                                     argc * kPointerSize)); | 
| 582   switch (function->shared()->builtin_function_id()) { | 590   switch (function->shared()->builtin_function_id()) { | 
| 583     case kStringCharCodeAt: | 591     case kStringCharCodeAt: | 
| 584     case kStringCharAt: | 592     case kStringCharAt: | 
| 585       if (object->IsString()) { | 593       if (object->IsString()) { | 
| 586         String* string = String::cast(*object); | 594         String* string = String::cast(*object); | 
| (...skipping 29 matching lines...) Expand all  Loading... | 
| 616     State state, | 624     State state, | 
| 617     Code::ExtraICState extra_ic_state, | 625     Code::ExtraICState extra_ic_state, | 
| 618     Handle<Object> object, | 626     Handle<Object> object, | 
| 619     Handle<String> name) { | 627     Handle<String> name) { | 
| 620   int argc = target()->arguments_count(); | 628   int argc = target()->arguments_count(); | 
| 621   InLoopFlag in_loop = target()->ic_in_loop(); | 629   InLoopFlag in_loop = target()->ic_in_loop(); | 
| 622   MaybeObject* maybe_code = NULL; | 630   MaybeObject* maybe_code = NULL; | 
| 623   switch (lookup->type()) { | 631   switch (lookup->type()) { | 
| 624     case FIELD: { | 632     case FIELD: { | 
| 625       int index = lookup->GetFieldIndex(); | 633       int index = lookup->GetFieldIndex(); | 
| 626       maybe_code = StubCache::ComputeCallField(argc, | 634       maybe_code = isolate()->stub_cache()->ComputeCallField(argc, | 
| 627                                                in_loop, | 635                                                              in_loop, | 
| 628                                                kind_, | 636                                                              kind_, | 
| 629                                                *name, | 637                                                              *name, | 
| 630                                                *object, | 638                                                              *object, | 
| 631                                                lookup->holder(), | 639                                                              lookup->holder(), | 
| 632                                                index); | 640                                                              index); | 
| 633       break; | 641       break; | 
| 634     } | 642     } | 
| 635     case CONSTANT_FUNCTION: { | 643     case CONSTANT_FUNCTION: { | 
| 636       // Get the constant function and compute the code stub for this | 644       // Get the constant function and compute the code stub for this | 
| 637       // call; used for rewriting to monomorphic state and making sure | 645       // call; used for rewriting to monomorphic state and making sure | 
| 638       // that the code stub is in the stub cache. | 646       // that the code stub is in the stub cache. | 
| 639       JSFunction* function = lookup->GetConstantFunction(); | 647       JSFunction* function = lookup->GetConstantFunction(); | 
| 640       maybe_code = StubCache::ComputeCallConstant(argc, | 648       maybe_code = | 
| 641                                                   in_loop, | 649           isolate()->stub_cache()->ComputeCallConstant(argc, | 
| 642                                                   kind_, | 650                                                        in_loop, | 
| 643                                                   extra_ic_state, | 651                                                        kind_, | 
| 644                                                   *name, | 652                                                        extra_ic_state, | 
| 645                                                   *object, | 653                                                        *name, | 
| 646                                                   lookup->holder(), | 654                                                        *object, | 
| 647                                                   function); | 655                                                        lookup->holder(), | 
|  | 656                                                        function); | 
| 648       break; | 657       break; | 
| 649     } | 658     } | 
| 650     case NORMAL: { | 659     case NORMAL: { | 
| 651       if (!object->IsJSObject()) return NULL; | 660       if (!object->IsJSObject()) return NULL; | 
| 652       Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 661       Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 
| 653 | 662 | 
| 654       if (lookup->holder()->IsGlobalObject()) { | 663       if (lookup->holder()->IsGlobalObject()) { | 
| 655         GlobalObject* global = GlobalObject::cast(lookup->holder()); | 664         GlobalObject* global = GlobalObject::cast(lookup->holder()); | 
| 656         JSGlobalPropertyCell* cell = | 665         JSGlobalPropertyCell* cell = | 
| 657             JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); | 666             JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); | 
| 658         if (!cell->value()->IsJSFunction()) return NULL; | 667         if (!cell->value()->IsJSFunction()) return NULL; | 
| 659         JSFunction* function = JSFunction::cast(cell->value()); | 668         JSFunction* function = JSFunction::cast(cell->value()); | 
| 660         maybe_code = StubCache::ComputeCallGlobal(argc, | 669         maybe_code = isolate()->stub_cache()->ComputeCallGlobal(argc, | 
| 661                                                   in_loop, | 670                                                                 in_loop, | 
| 662                                                   kind_, | 671                                                                 kind_, | 
| 663                                                   *name, | 672                                                                 *name, | 
| 664                                                   *receiver, | 673                                                                 *receiver, | 
| 665                                                   global, | 674                                                                 global, | 
| 666                                                   cell, | 675                                                                 cell, | 
| 667                                                   function); | 676                                                                 function); | 
| 668       } else { | 677       } else { | 
| 669         // There is only one shared stub for calling normalized | 678         // There is only one shared stub for calling normalized | 
| 670         // properties. It does not traverse the prototype chain, so the | 679         // properties. It does not traverse the prototype chain, so the | 
| 671         // property must be found in the receiver for the stub to be | 680         // property must be found in the receiver for the stub to be | 
| 672         // applicable. | 681         // applicable. | 
| 673         if (lookup->holder() != *receiver) return NULL; | 682         if (lookup->holder() != *receiver) return NULL; | 
| 674         maybe_code = StubCache::ComputeCallNormal(argc, | 683         maybe_code = isolate()->stub_cache()->ComputeCallNormal(argc, | 
| 675                                                   in_loop, | 684                                                                 in_loop, | 
| 676                                                   kind_, | 685                                                                 kind_, | 
| 677                                                   *name, | 686                                                                 *name, | 
| 678                                                   *receiver); | 687                                                                 *receiver); | 
| 679       } | 688       } | 
| 680       break; | 689       break; | 
| 681     } | 690     } | 
| 682     case INTERCEPTOR: { | 691     case INTERCEPTOR: { | 
| 683       ASSERT(HasInterceptorGetter(lookup->holder())); | 692       ASSERT(HasInterceptorGetter(lookup->holder())); | 
| 684       maybe_code = StubCache::ComputeCallInterceptor(argc, | 693       maybe_code = isolate()->stub_cache()->ComputeCallInterceptor( | 
| 685                                                      kind_, | 694           argc, | 
| 686                                                      *name, | 695           kind_, | 
| 687                                                      *object, | 696           *name, | 
| 688                                                      lookup->holder()); | 697           *object, | 
|  | 698           lookup->holder()); | 
| 689       break; | 699       break; | 
| 690     } | 700     } | 
| 691     default: | 701     default: | 
| 692       maybe_code = NULL; | 702       maybe_code = NULL; | 
| 693       break; | 703       break; | 
| 694   } | 704   } | 
| 695   return maybe_code; | 705   return maybe_code; | 
| 696 } | 706 } | 
| 697 | 707 | 
| 698 | 708 | 
| 699 void CallICBase::UpdateCaches(LookupResult* lookup, | 709 void CallICBase::UpdateCaches(LookupResult* lookup, | 
| 700                               State state, | 710                               State state, | 
| 701                               Code::ExtraICState extra_ic_state, | 711                               Code::ExtraICState extra_ic_state, | 
| 702                               Handle<Object> object, | 712                               Handle<Object> object, | 
| 703                               Handle<String> name) { | 713                               Handle<String> name) { | 
| 704   // Bail out if we didn't find a result. | 714   // Bail out if we didn't find a result. | 
| 705   if (!lookup->IsProperty() || !lookup->IsCacheable()) return; | 715   if (!lookup->IsProperty() || !lookup->IsCacheable()) return; | 
| 706 | 716 | 
| 707   if (lookup->holder() != *object && | 717   if (lookup->holder() != *object && | 
| 708       HasNormalObjectsInPrototypeChain(lookup, object->GetPrototype())) { | 718       HasNormalObjectsInPrototypeChain( | 
|  | 719           isolate(), lookup, object->GetPrototype())) { | 
| 709     // Suppress optimization for prototype chains with slow properties objects | 720     // Suppress optimization for prototype chains with slow properties objects | 
| 710     // in the middle. | 721     // in the middle. | 
| 711     return; | 722     return; | 
| 712   } | 723   } | 
| 713 | 724 | 
| 714   // Compute the number of arguments. | 725   // Compute the number of arguments. | 
| 715   int argc = target()->arguments_count(); | 726   int argc = target()->arguments_count(); | 
| 716   InLoopFlag in_loop = target()->ic_in_loop(); | 727   InLoopFlag in_loop = target()->ic_in_loop(); | 
| 717   MaybeObject* maybe_code = NULL; | 728   MaybeObject* maybe_code = NULL; | 
| 718   bool had_proto_failure = false; | 729   bool had_proto_failure = false; | 
| 719   if (state == UNINITIALIZED) { | 730   if (state == UNINITIALIZED) { | 
| 720     // This is the first time we execute this inline cache. | 731     // This is the first time we execute this inline cache. | 
| 721     // Set the target to the pre monomorphic stub to delay | 732     // Set the target to the pre monomorphic stub to delay | 
| 722     // setting the monomorphic state. | 733     // setting the monomorphic state. | 
| 723     maybe_code = StubCache::ComputeCallPreMonomorphic(argc, in_loop, kind_); | 734     maybe_code = isolate()->stub_cache()->ComputeCallPreMonomorphic(argc, | 
|  | 735                                                                     in_loop, | 
|  | 736                                                                     kind_); | 
| 724   } else if (state == MONOMORPHIC) { | 737   } else if (state == MONOMORPHIC) { | 
| 725     if (kind_ == Code::CALL_IC && | 738     if (kind_ == Code::CALL_IC && | 
| 726         TryUpdateExtraICState(lookup, object, &extra_ic_state)) { | 739         TryUpdateExtraICState(lookup, object, &extra_ic_state)) { | 
| 727       maybe_code = ComputeMonomorphicStub(lookup, | 740       maybe_code = ComputeMonomorphicStub(lookup, | 
| 728                                           state, | 741                                           state, | 
| 729                                           extra_ic_state, | 742                                           extra_ic_state, | 
| 730                                           object, | 743                                           object, | 
| 731                                           name); | 744                                           name); | 
| 732     } else if (kind_ == Code::CALL_IC && | 745     } else if (kind_ == Code::CALL_IC && | 
| 733                TryRemoveInvalidPrototypeDependentStub(target(), | 746                TryRemoveInvalidPrototypeDependentStub(target(), | 
| 734                                                       *object, | 747                                                       *object, | 
| 735                                                       *name)) { | 748                                                       *name)) { | 
| 736       had_proto_failure = true; | 749       had_proto_failure = true; | 
| 737       maybe_code = ComputeMonomorphicStub(lookup, | 750       maybe_code = ComputeMonomorphicStub(lookup, | 
| 738                                           state, | 751                                           state, | 
| 739                                           extra_ic_state, | 752                                           extra_ic_state, | 
| 740                                           object, | 753                                           object, | 
| 741                                           name); | 754                                           name); | 
| 742     } else { | 755     } else { | 
| 743       maybe_code = StubCache::ComputeCallMegamorphic(argc, in_loop, kind_); | 756       maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic(argc, | 
|  | 757                                                                    in_loop, | 
|  | 758                                                                    kind_); | 
| 744     } | 759     } | 
| 745   } else { | 760   } else { | 
| 746     maybe_code = ComputeMonomorphicStub(lookup, | 761     maybe_code = ComputeMonomorphicStub(lookup, | 
| 747                                         state, | 762                                         state, | 
| 748                                         extra_ic_state, | 763                                         extra_ic_state, | 
| 749                                         object, | 764                                         object, | 
| 750                                         name); | 765                                         name); | 
| 751   } | 766   } | 
| 752 | 767 | 
| 753   // If we're unable to compute the stub (not enough memory left), we | 768   // If we're unable to compute the stub (not enough memory left), we | 
| 754   // simply avoid updating the caches. | 769   // simply avoid updating the caches. | 
| 755   Object* code; | 770   Object* code; | 
| 756   if (maybe_code == NULL || !maybe_code->ToObject(&code)) return; | 771   if (maybe_code == NULL || !maybe_code->ToObject(&code)) return; | 
| 757 | 772 | 
| 758   // Patch the call site depending on the state of the cache. | 773   // Patch the call site depending on the state of the cache. | 
| 759   if (state == UNINITIALIZED || | 774   if (state == UNINITIALIZED || | 
| 760       state == PREMONOMORPHIC || | 775       state == PREMONOMORPHIC || | 
| 761       state == MONOMORPHIC || | 776       state == MONOMORPHIC || | 
| 762       state == MONOMORPHIC_PROTOTYPE_FAILURE) { | 777       state == MONOMORPHIC_PROTOTYPE_FAILURE) { | 
| 763     set_target(Code::cast(code)); | 778     set_target(Code::cast(code)); | 
| 764   } else if (state == MEGAMORPHIC) { | 779   } else if (state == MEGAMORPHIC) { | 
| 765     // Cache code holding map should be consistent with | 780     // Cache code holding map should be consistent with | 
| 766     // GenerateMonomorphicCacheProbe. It is not the map which holds the stub. | 781     // GenerateMonomorphicCacheProbe. It is not the map which holds the stub. | 
| 767     Map* map = JSObject::cast(object->IsJSObject() ? *object : | 782     Map* map = JSObject::cast(object->IsJSObject() ? *object : | 
| 768                               object->GetPrototype())->map(); | 783                               object->GetPrototype())->map(); | 
| 769 | 784 | 
| 770     // Update the stub cache. | 785     // Update the stub cache. | 
| 771     StubCache::Set(*name, map, Code::cast(code)); | 786     isolate()->stub_cache()->Set(*name, map, Code::cast(code)); | 
| 772   } | 787   } | 
| 773 | 788 | 
| 774   USE(had_proto_failure); | 789   USE(had_proto_failure); | 
| 775 #ifdef DEBUG | 790 #ifdef DEBUG | 
| 776   if (had_proto_failure) state = MONOMORPHIC_PROTOTYPE_FAILURE; | 791   if (had_proto_failure) state = MONOMORPHIC_PROTOTYPE_FAILURE; | 
| 777   TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", | 792   TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", | 
| 778       name, state, target(), in_loop ? " (in-loop)" : ""); | 793       name, state, target(), in_loop ? " (in-loop)" : ""); | 
| 779 #endif | 794 #endif | 
| 780 } | 795 } | 
| 781 | 796 | 
| 782 | 797 | 
| 783 MaybeObject* KeyedCallIC::LoadFunction(State state, | 798 MaybeObject* KeyedCallIC::LoadFunction(State state, | 
| 784                                        Handle<Object> object, | 799                                        Handle<Object> object, | 
| 785                                        Handle<Object> key) { | 800                                        Handle<Object> key) { | 
| 786   if (key->IsSymbol()) { | 801   if (key->IsSymbol()) { | 
| 787     return CallICBase::LoadFunction(state, | 802     return CallICBase::LoadFunction(state, | 
| 788                                     Code::kNoExtraICState, | 803                                     Code::kNoExtraICState, | 
| 789                                     object, | 804                                     object, | 
| 790                                     Handle<String>::cast(key)); | 805                                     Handle<String>::cast(key)); | 
| 791   } | 806   } | 
| 792 | 807 | 
| 793   if (object->IsUndefined() || object->IsNull()) { | 808   if (object->IsUndefined() || object->IsNull()) { | 
| 794     return TypeError("non_object_property_call", object, key); | 809     return TypeError("non_object_property_call", object, key); | 
| 795   } | 810   } | 
| 796 | 811 | 
| 797   if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) { | 812   if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) { | 
| 798     int argc = target()->arguments_count(); | 813     int argc = target()->arguments_count(); | 
| 799     InLoopFlag in_loop = target()->ic_in_loop(); | 814     InLoopFlag in_loop = target()->ic_in_loop(); | 
| 800     MaybeObject* maybe_code = StubCache::ComputeCallMegamorphic( | 815     MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic( | 
| 801         argc, in_loop, Code::KEYED_CALL_IC); | 816         argc, in_loop, Code::KEYED_CALL_IC); | 
| 802     Object* code; | 817     Object* code; | 
| 803     if (maybe_code->ToObject(&code)) { | 818     if (maybe_code->ToObject(&code)) { | 
| 804       set_target(Code::cast(code)); | 819       set_target(Code::cast(code)); | 
| 805 #ifdef DEBUG | 820 #ifdef DEBUG | 
| 806       TraceIC( | 821       TraceIC( | 
| 807           "KeyedCallIC", key, state, target(), in_loop ? " (in-loop)" : ""); | 822           "KeyedCallIC", key, state, target(), in_loop ? " (in-loop)" : ""); | 
| 808 #endif | 823 #endif | 
| 809     } | 824     } | 
| 810   } | 825   } | 
| 811 | 826 | 
| 812   HandleScope scope; | 827   HandleScope scope(isolate()); | 
| 813   Handle<Object> result = GetProperty(object, key); | 828   Handle<Object> result = GetProperty(object, key); | 
| 814   RETURN_IF_EMPTY_HANDLE(result); | 829   RETURN_IF_EMPTY_HANDLE(isolate(), result); | 
| 815 | 830 | 
| 816   // Make receiver an object if the callee requires it. Strict mode or builtin | 831   // Make receiver an object if the callee requires it. Strict mode or builtin | 
| 817   // functions do not wrap the receiver, non-strict functions and objects | 832   // functions do not wrap the receiver, non-strict functions and objects | 
| 818   // called as functions do. | 833   // called as functions do. | 
| 819   ReceiverToObjectIfRequired(result, object); | 834   ReceiverToObjectIfRequired(result, object); | 
| 820 | 835 | 
| 821   if (result->IsJSFunction()) return *result; | 836   if (result->IsJSFunction()) return *result; | 
| 822   result = Handle<Object>(TryCallAsFunction(*result)); | 837   result = Handle<Object>(TryCallAsFunction(*result)); | 
| 823   if (result->IsJSFunction()) return *result; | 838   if (result->IsJSFunction()) return *result; | 
| 824 | 839 | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
| 845 | 860 | 
| 846   if (FLAG_use_ic) { | 861   if (FLAG_use_ic) { | 
| 847     Code* non_monomorphic_stub = | 862     Code* non_monomorphic_stub = | 
| 848         (state == UNINITIALIZED) ? pre_monomorphic_stub() : megamorphic_stub(); | 863         (state == UNINITIALIZED) ? pre_monomorphic_stub() : megamorphic_stub(); | 
| 849 | 864 | 
| 850     // Use specialized code for getting the length of strings and | 865     // Use specialized code for getting the length of strings and | 
| 851     // string wrapper objects.  The length property of string wrapper | 866     // string wrapper objects.  The length property of string wrapper | 
| 852     // objects is read-only and therefore always returns the length of | 867     // objects is read-only and therefore always returns the length of | 
| 853     // the underlying string value.  See ECMA-262 15.5.5.1. | 868     // the underlying string value.  See ECMA-262 15.5.5.1. | 
| 854     if ((object->IsString() || object->IsStringWrapper()) && | 869     if ((object->IsString() || object->IsStringWrapper()) && | 
| 855         name->Equals(Heap::length_symbol())) { | 870         name->Equals(isolate()->heap()->length_symbol())) { | 
| 856       HandleScope scope; | 871       HandleScope scope(isolate()); | 
| 857 #ifdef DEBUG | 872 #ifdef DEBUG | 
| 858       if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n"); | 873       if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n"); | 
| 859 #endif | 874 #endif | 
| 860       if (state == PREMONOMORPHIC) { | 875       if (state == PREMONOMORPHIC) { | 
| 861         if (object->IsString()) { | 876         if (object->IsString()) { | 
| 862           Map* map = HeapObject::cast(*object)->map(); | 877           Map* map = HeapObject::cast(*object)->map(); | 
| 863           const int offset = String::kLengthOffset; | 878           const int offset = String::kLengthOffset; | 
| 864           PatchInlinedLoad(address(), map, offset); | 879           PatchInlinedLoad(address(), map, offset); | 
| 865           set_target(Builtins::builtin(Builtins::LoadIC_StringLength)); | 880           set_target(isolate()->builtins()->builtin( | 
|  | 881               Builtins::LoadIC_StringLength)); | 
| 866         } else { | 882         } else { | 
| 867           set_target(Builtins::builtin(Builtins::LoadIC_StringWrapperLength)); | 883           set_target(isolate()->builtins()->builtin( | 
|  | 884               Builtins::LoadIC_StringWrapperLength)); | 
| 868         } | 885         } | 
| 869       } else if (state == MONOMORPHIC && object->IsStringWrapper()) { | 886       } else if (state == MONOMORPHIC && object->IsStringWrapper()) { | 
| 870         set_target(Builtins::builtin(Builtins::LoadIC_StringWrapperLength)); | 887         set_target(isolate()->builtins()->builtin( | 
|  | 888             Builtins::LoadIC_StringWrapperLength)); | 
| 871       } else { | 889       } else { | 
| 872         set_target(non_monomorphic_stub); | 890         set_target(non_monomorphic_stub); | 
| 873       } | 891       } | 
| 874       // Get the string if we have a string wrapper object. | 892       // Get the string if we have a string wrapper object. | 
| 875       if (object->IsJSValue()) { | 893       if (object->IsJSValue()) { | 
| 876         object = Handle<Object>(Handle<JSValue>::cast(object)->value()); | 894         object = Handle<Object>(Handle<JSValue>::cast(object)->value(), | 
|  | 895                                 isolate()); | 
| 877       } | 896       } | 
| 878       return Smi::FromInt(String::cast(*object)->length()); | 897       return Smi::FromInt(String::cast(*object)->length()); | 
| 879     } | 898     } | 
| 880 | 899 | 
| 881     // Use specialized code for getting the length of arrays. | 900     // Use specialized code for getting the length of arrays. | 
| 882     if (object->IsJSArray() && name->Equals(Heap::length_symbol())) { | 901     if (object->IsJSArray() && | 
|  | 902         name->Equals(isolate()->heap()->length_symbol())) { | 
| 883 #ifdef DEBUG | 903 #ifdef DEBUG | 
| 884       if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n"); | 904       if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n"); | 
| 885 #endif | 905 #endif | 
| 886       if (state == PREMONOMORPHIC) { | 906       if (state == PREMONOMORPHIC) { | 
| 887         Map* map = HeapObject::cast(*object)->map(); | 907         Map* map = HeapObject::cast(*object)->map(); | 
| 888         const int offset = JSArray::kLengthOffset; | 908         const int offset = JSArray::kLengthOffset; | 
| 889         PatchInlinedLoad(address(), map, offset); | 909         PatchInlinedLoad(address(), map, offset); | 
| 890         set_target(Builtins::builtin(Builtins::LoadIC_ArrayLength)); | 910         set_target(isolate()->builtins()->builtin( | 
|  | 911             Builtins::LoadIC_ArrayLength)); | 
| 891       } else { | 912       } else { | 
| 892         set_target(non_monomorphic_stub); | 913         set_target(non_monomorphic_stub); | 
| 893       } | 914       } | 
| 894       return JSArray::cast(*object)->length(); | 915       return JSArray::cast(*object)->length(); | 
| 895     } | 916     } | 
| 896 | 917 | 
| 897     // Use specialized code for getting prototype of functions. | 918     // Use specialized code for getting prototype of functions. | 
| 898     if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol()) && | 919     if (object->IsJSFunction() && | 
|  | 920         name->Equals(isolate()->heap()->prototype_symbol()) && | 
| 899         JSFunction::cast(*object)->should_have_prototype()) { | 921         JSFunction::cast(*object)->should_have_prototype()) { | 
| 900 #ifdef DEBUG | 922 #ifdef DEBUG | 
| 901       if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); | 923       if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); | 
| 902 #endif | 924 #endif | 
| 903       if (state == PREMONOMORPHIC) { | 925       if (state == PREMONOMORPHIC) { | 
| 904         set_target(Builtins::builtin(Builtins::LoadIC_FunctionPrototype)); | 926         set_target(isolate()->builtins()->builtin( | 
|  | 927             Builtins::LoadIC_FunctionPrototype)); | 
| 905       } else { | 928       } else { | 
| 906         set_target(non_monomorphic_stub); | 929         set_target(non_monomorphic_stub); | 
| 907       } | 930       } | 
| 908       return Accessors::FunctionGetPrototype(*object, 0); | 931       return Accessors::FunctionGetPrototype(*object, 0); | 
| 909     } | 932     } | 
| 910   } | 933   } | 
| 911 | 934 | 
| 912   // Check if the name is trivially convertible to an index and get | 935   // Check if the name is trivially convertible to an index and get | 
| 913   // the element if so. | 936   // the element if so. | 
| 914   uint32_t index; | 937   uint32_t index; | 
| 915   if (name->AsArrayIndex(&index)) return object->GetElement(index); | 938   if (name->AsArrayIndex(&index)) return object->GetElement(index); | 
| 916 | 939 | 
| 917   // Named lookup in the object. | 940   // Named lookup in the object. | 
| 918   LookupResult lookup; | 941   LookupResult lookup; | 
| 919   LookupForRead(*object, *name, &lookup); | 942   LookupForRead(*object, *name, &lookup); | 
| 920 | 943 | 
| 921   // If we did not find a property, check if we need to throw an exception. | 944   // If we did not find a property, check if we need to throw an exception. | 
| 922   if (!lookup.IsProperty()) { | 945   if (!lookup.IsProperty()) { | 
| 923     if (FLAG_strict || IsContextual(object)) { | 946     if (FLAG_strict || IsContextual(object)) { | 
| 924       return ReferenceError("not_defined", name); | 947       return ReferenceError("not_defined", name); | 
| 925     } | 948     } | 
| 926     LOG(SuspectReadEvent(*name, *object)); | 949     LOG(isolate(), SuspectReadEvent(*name, *object)); | 
| 927   } | 950   } | 
| 928 | 951 | 
| 929   bool can_be_inlined_precheck = | 952   bool can_be_inlined_precheck = | 
| 930       FLAG_use_ic && | 953       FLAG_use_ic && | 
| 931       lookup.IsProperty() && | 954       lookup.IsProperty() && | 
| 932       lookup.IsCacheable() && | 955       lookup.IsCacheable() && | 
| 933       lookup.holder() == *object && | 956       lookup.holder() == *object && | 
| 934       !object->IsAccessCheckNeeded(); | 957       !object->IsAccessCheckNeeded(); | 
| 935 | 958 | 
| 936   bool can_be_inlined = | 959   bool can_be_inlined = | 
| (...skipping 30 matching lines...) Expand all  Loading... | 
| 967     Map* map = lookup.holder()->map(); | 990     Map* map = lookup.holder()->map(); | 
| 968     JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast( | 991     JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast( | 
| 969         lookup.holder()->property_dictionary()->ValueAt( | 992         lookup.holder()->property_dictionary()->ValueAt( | 
| 970             lookup.GetDictionaryEntry())); | 993             lookup.GetDictionaryEntry())); | 
| 971     if (PatchInlinedContextualLoad(address(), | 994     if (PatchInlinedContextualLoad(address(), | 
| 972                                    map, | 995                                    map, | 
| 973                                    cell, | 996                                    cell, | 
| 974                                    lookup.IsDontDelete())) { | 997                                    lookup.IsDontDelete())) { | 
| 975       set_target(megamorphic_stub()); | 998       set_target(megamorphic_stub()); | 
| 976       TRACE_IC_NAMED("[LoadIC : inline contextual patch %s]\n", name); | 999       TRACE_IC_NAMED("[LoadIC : inline contextual patch %s]\n", name); | 
| 977       ASSERT(cell->value() != Heap::the_hole_value()); | 1000       ASSERT(cell->value() != isolate()->heap()->the_hole_value()); | 
| 978       return cell->value(); | 1001       return cell->value(); | 
| 979     } | 1002     } | 
| 980   } else { | 1003   } else { | 
| 981     if (FLAG_use_ic && state == PREMONOMORPHIC) { | 1004     if (FLAG_use_ic && state == PREMONOMORPHIC) { | 
| 982       TRACE_IC_NAMED("[LoadIC : no inline patch %s (not inlinable)]\n", name); | 1005       TRACE_IC_NAMED("[LoadIC : no inline patch %s (not inlinable)]\n", name); | 
| 983     } | 1006     } | 
| 984   } | 1007   } | 
| 985 | 1008 | 
| 986   // Update inline cache and stub cache. | 1009   // Update inline cache and stub cache. | 
| 987   if (FLAG_use_ic) { | 1010   if (FLAG_use_ic) { | 
| (...skipping 26 matching lines...) Expand all  Loading... | 
| 1014                           Handle<Object> object, | 1037                           Handle<Object> object, | 
| 1015                           Handle<String> name) { | 1038                           Handle<String> name) { | 
| 1016   // Bail out if the result is not cacheable. | 1039   // Bail out if the result is not cacheable. | 
| 1017   if (!lookup->IsCacheable()) return; | 1040   if (!lookup->IsCacheable()) return; | 
| 1018 | 1041 | 
| 1019   // Loading properties from values is not common, so don't try to | 1042   // Loading properties from values is not common, so don't try to | 
| 1020   // deal with non-JS objects here. | 1043   // deal with non-JS objects here. | 
| 1021   if (!object->IsJSObject()) return; | 1044   if (!object->IsJSObject()) return; | 
| 1022   Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1045   Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 
| 1023 | 1046 | 
| 1024   if (HasNormalObjectsInPrototypeChain(lookup, *object)) return; | 1047   if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return; | 
| 1025 | 1048 | 
| 1026   // Compute the code stub for this load. | 1049   // Compute the code stub for this load. | 
| 1027   MaybeObject* maybe_code = NULL; | 1050   MaybeObject* maybe_code = NULL; | 
| 1028   Object* code; | 1051   Object* code; | 
| 1029   if (state == UNINITIALIZED) { | 1052   if (state == UNINITIALIZED) { | 
| 1030     // This is the first time we execute this inline cache. | 1053     // This is the first time we execute this inline cache. | 
| 1031     // Set the target to the pre monomorphic stub to delay | 1054     // Set the target to the pre monomorphic stub to delay | 
| 1032     // setting the monomorphic state. | 1055     // setting the monomorphic state. | 
| 1033     maybe_code = pre_monomorphic_stub(); | 1056     maybe_code = pre_monomorphic_stub(); | 
| 1034   } else if (!lookup->IsProperty()) { | 1057   } else if (!lookup->IsProperty()) { | 
| 1035     // Nonexistent property. The result is undefined. | 1058     // Nonexistent property. The result is undefined. | 
| 1036     maybe_code = StubCache::ComputeLoadNonexistent(*name, *receiver); | 1059     maybe_code = isolate()->stub_cache()->ComputeLoadNonexistent(*name, | 
|  | 1060                                                                  *receiver); | 
| 1037   } else { | 1061   } else { | 
| 1038     // Compute monomorphic stub. | 1062     // Compute monomorphic stub. | 
| 1039     switch (lookup->type()) { | 1063     switch (lookup->type()) { | 
| 1040       case FIELD: { | 1064       case FIELD: { | 
| 1041         maybe_code = StubCache::ComputeLoadField(*name, *receiver, | 1065         maybe_code = isolate()->stub_cache()->ComputeLoadField( | 
| 1042                                                  lookup->holder(), | 1066             *name, | 
| 1043                                                  lookup->GetFieldIndex()); | 1067             *receiver, | 
|  | 1068             lookup->holder(), | 
|  | 1069             lookup->GetFieldIndex()); | 
| 1044         break; | 1070         break; | 
| 1045       } | 1071       } | 
| 1046       case CONSTANT_FUNCTION: { | 1072       case CONSTANT_FUNCTION: { | 
| 1047         Object* constant = lookup->GetConstantFunction(); | 1073         Object* constant = lookup->GetConstantFunction(); | 
| 1048         maybe_code = StubCache::ComputeLoadConstant(*name, *receiver, | 1074         maybe_code = isolate()->stub_cache()->ComputeLoadConstant( | 
| 1049                                                     lookup->holder(), constant); | 1075             *name, *receiver, lookup->holder(), constant); | 
| 1050         break; | 1076         break; | 
| 1051       } | 1077       } | 
| 1052       case NORMAL: { | 1078       case NORMAL: { | 
| 1053         if (lookup->holder()->IsGlobalObject()) { | 1079         if (lookup->holder()->IsGlobalObject()) { | 
| 1054           GlobalObject* global = GlobalObject::cast(lookup->holder()); | 1080           GlobalObject* global = GlobalObject::cast(lookup->holder()); | 
| 1055           JSGlobalPropertyCell* cell = | 1081           JSGlobalPropertyCell* cell = | 
| 1056               JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); | 1082               JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); | 
| 1057           maybe_code = StubCache::ComputeLoadGlobal(*name, | 1083           maybe_code = isolate()->stub_cache()->ComputeLoadGlobal(*name, | 
| 1058                                                     *receiver, | 1084                                                     *receiver, | 
| 1059                                                     global, | 1085                                                     global, | 
| 1060                                                     cell, | 1086                                                     cell, | 
| 1061                                                     lookup->IsDontDelete()); | 1087                                                     lookup->IsDontDelete()); | 
| 1062         } else { | 1088         } else { | 
| 1063           // There is only one shared stub for loading normalized | 1089           // There is only one shared stub for loading normalized | 
| 1064           // properties. It does not traverse the prototype chain, so the | 1090           // properties. It does not traverse the prototype chain, so the | 
| 1065           // property must be found in the receiver for the stub to be | 1091           // property must be found in the receiver for the stub to be | 
| 1066           // applicable. | 1092           // applicable. | 
| 1067           if (lookup->holder() != *receiver) return; | 1093           if (lookup->holder() != *receiver) return; | 
| 1068           maybe_code = StubCache::ComputeLoadNormal(); | 1094           maybe_code = isolate()->stub_cache()->ComputeLoadNormal(); | 
| 1069         } | 1095         } | 
| 1070         break; | 1096         break; | 
| 1071       } | 1097       } | 
| 1072       case CALLBACKS: { | 1098       case CALLBACKS: { | 
| 1073         if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; | 1099         if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; | 
| 1074         AccessorInfo* callback = | 1100         AccessorInfo* callback = | 
| 1075             AccessorInfo::cast(lookup->GetCallbackObject()); | 1101             AccessorInfo::cast(lookup->GetCallbackObject()); | 
| 1076         if (v8::ToCData<Address>(callback->getter()) == 0) return; | 1102         if (v8::ToCData<Address>(callback->getter()) == 0) return; | 
| 1077         maybe_code = StubCache::ComputeLoadCallback(*name, *receiver, | 1103         maybe_code = isolate()->stub_cache()->ComputeLoadCallback( | 
| 1078                                                     lookup->holder(), callback); | 1104             *name, *receiver, lookup->holder(), callback); | 
| 1079         break; | 1105         break; | 
| 1080       } | 1106       } | 
| 1081       case INTERCEPTOR: { | 1107       case INTERCEPTOR: { | 
| 1082         ASSERT(HasInterceptorGetter(lookup->holder())); | 1108         ASSERT(HasInterceptorGetter(lookup->holder())); | 
| 1083         maybe_code = StubCache::ComputeLoadInterceptor(*name, *receiver, | 1109         maybe_code = isolate()->stub_cache()->ComputeLoadInterceptor( | 
| 1084                                                        lookup->holder()); | 1110             *name, *receiver, lookup->holder()); | 
| 1085         break; | 1111         break; | 
| 1086       } | 1112       } | 
| 1087       default: | 1113       default: | 
| 1088         return; | 1114         return; | 
| 1089     } | 1115     } | 
| 1090   } | 1116   } | 
| 1091 | 1117 | 
| 1092   // If we're unable to compute the stub (not enough memory left), we | 1118   // If we're unable to compute the stub (not enough memory left), we | 
| 1093   // simply avoid updating the caches. | 1119   // simply avoid updating the caches. | 
| 1094   if (maybe_code == NULL || !maybe_code->ToObject(&code)) return; | 1120   if (maybe_code == NULL || !maybe_code->ToObject(&code)) return; | 
| 1095 | 1121 | 
| 1096   // Patch the call site depending on the state of the cache. | 1122   // Patch the call site depending on the state of the cache. | 
| 1097   if (state == UNINITIALIZED || state == PREMONOMORPHIC || | 1123   if (state == UNINITIALIZED || state == PREMONOMORPHIC || | 
| 1098       state == MONOMORPHIC_PROTOTYPE_FAILURE) { | 1124       state == MONOMORPHIC_PROTOTYPE_FAILURE) { | 
| 1099     set_target(Code::cast(code)); | 1125     set_target(Code::cast(code)); | 
| 1100   } else if (state == MONOMORPHIC) { | 1126   } else if (state == MONOMORPHIC) { | 
| 1101     set_target(megamorphic_stub()); | 1127     set_target(megamorphic_stub()); | 
| 1102   } else if (state == MEGAMORPHIC) { | 1128   } else if (state == MEGAMORPHIC) { | 
| 1103     // Cache code holding map should be consistent with | 1129     // Cache code holding map should be consistent with | 
| 1104     // GenerateMonomorphicCacheProbe. | 1130     // GenerateMonomorphicCacheProbe. | 
| 1105     Map* map = JSObject::cast(object->IsJSObject() ? *object : | 1131     Map* map = JSObject::cast(object->IsJSObject() ? *object : | 
| 1106                               object->GetPrototype())->map(); | 1132                               object->GetPrototype())->map(); | 
| 1107 | 1133 | 
| 1108     StubCache::Set(*name, map, Code::cast(code)); | 1134     isolate()->stub_cache()->Set(*name, map, Code::cast(code)); | 
| 1109   } | 1135   } | 
| 1110 | 1136 | 
| 1111 #ifdef DEBUG | 1137 #ifdef DEBUG | 
| 1112   TraceIC("LoadIC", name, state, target()); | 1138   TraceIC("LoadIC", name, state, target()); | 
| 1113 #endif | 1139 #endif | 
| 1114 } | 1140 } | 
| 1115 | 1141 | 
| 1116 | 1142 | 
| 1117 MaybeObject* KeyedLoadIC::Load(State state, | 1143 MaybeObject* KeyedLoadIC::Load(State state, | 
| 1118                                Handle<Object> object, | 1144                                Handle<Object> object, | 
| 1119                                Handle<Object> key) { | 1145                                Handle<Object> key) { | 
| 1120   if (key->IsSymbol()) { | 1146   if (key->IsSymbol()) { | 
| 1121     Handle<String> name = Handle<String>::cast(key); | 1147     Handle<String> name = Handle<String>::cast(key); | 
| 1122 | 1148 | 
| 1123     // If the object is undefined or null it's illegal to try to get any | 1149     // If the object is undefined or null it's illegal to try to get any | 
| 1124     // of its properties; throw a TypeError in that case. | 1150     // of its properties; throw a TypeError in that case. | 
| 1125     if (object->IsUndefined() || object->IsNull()) { | 1151     if (object->IsUndefined() || object->IsNull()) { | 
| 1126       return TypeError("non_object_property_load", object, name); | 1152       return TypeError("non_object_property_load", object, name); | 
| 1127     } | 1153     } | 
| 1128 | 1154 | 
| 1129     if (FLAG_use_ic) { | 1155     if (FLAG_use_ic) { | 
| 1130       // TODO(1073): don't ignore the current stub state. | 1156       // TODO(1073): don't ignore the current stub state. | 
| 1131 | 1157 | 
| 1132       // Use specialized code for getting the length of strings. | 1158       // Use specialized code for getting the length of strings. | 
| 1133       if (object->IsString() && name->Equals(Heap::length_symbol())) { | 1159       if (object->IsString() && | 
|  | 1160           name->Equals(isolate()->heap()->length_symbol())) { | 
| 1134         Handle<String> string = Handle<String>::cast(object); | 1161         Handle<String> string = Handle<String>::cast(object); | 
| 1135         Object* code = NULL; | 1162         Object* code = NULL; | 
| 1136         { MaybeObject* maybe_code = | 1163         { MaybeObject* maybe_code = | 
| 1137               StubCache::ComputeKeyedLoadStringLength(*name, *string); | 1164               isolate()->stub_cache()->ComputeKeyedLoadStringLength(*name, | 
|  | 1165                                                                     *string); | 
| 1138           if (!maybe_code->ToObject(&code)) return maybe_code; | 1166           if (!maybe_code->ToObject(&code)) return maybe_code; | 
| 1139         } | 1167         } | 
| 1140         set_target(Code::cast(code)); | 1168         set_target(Code::cast(code)); | 
| 1141 #ifdef DEBUG | 1169 #ifdef DEBUG | 
| 1142         TraceIC("KeyedLoadIC", name, state, target()); | 1170         TraceIC("KeyedLoadIC", name, state, target()); | 
| 1143 #endif  // DEBUG | 1171 #endif  // DEBUG | 
| 1144         return Smi::FromInt(string->length()); | 1172         return Smi::FromInt(string->length()); | 
| 1145       } | 1173       } | 
| 1146 | 1174 | 
| 1147       // Use specialized code for getting the length of arrays. | 1175       // Use specialized code for getting the length of arrays. | 
| 1148       if (object->IsJSArray() && name->Equals(Heap::length_symbol())) { | 1176       if (object->IsJSArray() && | 
|  | 1177           name->Equals(isolate()->heap()->length_symbol())) { | 
| 1149         Handle<JSArray> array = Handle<JSArray>::cast(object); | 1178         Handle<JSArray> array = Handle<JSArray>::cast(object); | 
| 1150         Object* code; | 1179         Object* code; | 
| 1151         { MaybeObject* maybe_code = | 1180         { MaybeObject* maybe_code = | 
| 1152               StubCache::ComputeKeyedLoadArrayLength(*name, *array); | 1181               isolate()->stub_cache()->ComputeKeyedLoadArrayLength(*name, | 
|  | 1182                                                                    *array); | 
| 1153           if (!maybe_code->ToObject(&code)) return maybe_code; | 1183           if (!maybe_code->ToObject(&code)) return maybe_code; | 
| 1154         } | 1184         } | 
| 1155         set_target(Code::cast(code)); | 1185         set_target(Code::cast(code)); | 
| 1156 #ifdef DEBUG | 1186 #ifdef DEBUG | 
| 1157         TraceIC("KeyedLoadIC", name, state, target()); | 1187         TraceIC("KeyedLoadIC", name, state, target()); | 
| 1158 #endif  // DEBUG | 1188 #endif  // DEBUG | 
| 1159         return JSArray::cast(*object)->length(); | 1189         return JSArray::cast(*object)->length(); | 
| 1160       } | 1190       } | 
| 1161 | 1191 | 
| 1162       // Use specialized code for getting prototype of functions. | 1192       // Use specialized code for getting prototype of functions. | 
| 1163       if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol()) && | 1193       if (object->IsJSFunction() && | 
|  | 1194           name->Equals(isolate()->heap()->prototype_symbol()) && | 
| 1164         JSFunction::cast(*object)->should_have_prototype()) { | 1195         JSFunction::cast(*object)->should_have_prototype()) { | 
| 1165         Handle<JSFunction> function = Handle<JSFunction>::cast(object); | 1196         Handle<JSFunction> function = Handle<JSFunction>::cast(object); | 
| 1166         Object* code; | 1197         Object* code; | 
| 1167         { MaybeObject* maybe_code = | 1198         { MaybeObject* maybe_code = | 
| 1168               StubCache::ComputeKeyedLoadFunctionPrototype(*name, *function); | 1199               isolate()->stub_cache()->ComputeKeyedLoadFunctionPrototype( | 
|  | 1200                   *name, *function); | 
| 1169           if (!maybe_code->ToObject(&code)) return maybe_code; | 1201           if (!maybe_code->ToObject(&code)) return maybe_code; | 
| 1170         } | 1202         } | 
| 1171         set_target(Code::cast(code)); | 1203         set_target(Code::cast(code)); | 
| 1172 #ifdef DEBUG | 1204 #ifdef DEBUG | 
| 1173         TraceIC("KeyedLoadIC", name, state, target()); | 1205         TraceIC("KeyedLoadIC", name, state, target()); | 
| 1174 #endif  // DEBUG | 1206 #endif  // DEBUG | 
| 1175         return Accessors::FunctionGetPrototype(*object, 0); | 1207         return Accessors::FunctionGetPrototype(*object, 0); | 
| 1176       } | 1208       } | 
| 1177     } | 1209     } | 
| 1178 | 1210 | 
| 1179     // Check if the name is trivially convertible to an index and get | 1211     // Check if the name is trivially convertible to an index and get | 
| 1180     // the element or char if so. | 1212     // the element or char if so. | 
| 1181     uint32_t index = 0; | 1213     uint32_t index = 0; | 
| 1182     if (name->AsArrayIndex(&index)) { | 1214     if (name->AsArrayIndex(&index)) { | 
| 1183       HandleScope scope; | 1215       HandleScope scope(isolate()); | 
| 1184       // Rewrite to the generic keyed load stub. | 1216       // Rewrite to the generic keyed load stub. | 
| 1185       if (FLAG_use_ic) set_target(generic_stub()); | 1217       if (FLAG_use_ic) set_target(generic_stub()); | 
| 1186       return Runtime::GetElementOrCharAt(object, index); | 1218       return Runtime::GetElementOrCharAt(isolate(), object, index); | 
| 1187     } | 1219     } | 
| 1188 | 1220 | 
| 1189     // Named lookup. | 1221     // Named lookup. | 
| 1190     LookupResult lookup; | 1222     LookupResult lookup; | 
| 1191     LookupForRead(*object, *name, &lookup); | 1223     LookupForRead(*object, *name, &lookup); | 
| 1192 | 1224 | 
| 1193     // If we did not find a property, check if we need to throw an exception. | 1225     // If we did not find a property, check if we need to throw an exception. | 
| 1194     if (!lookup.IsProperty()) { | 1226     if (!lookup.IsProperty()) { | 
| 1195       if (FLAG_strict || IsContextual(object)) { | 1227       if (FLAG_strict || IsContextual(object)) { | 
| 1196         return ReferenceError("not_defined", name); | 1228         return ReferenceError("not_defined", name); | 
| (...skipping 29 matching lines...) Expand all  Loading... | 
| 1226 | 1258 | 
| 1227   if (use_ic) { | 1259   if (use_ic) { | 
| 1228     Code* stub = generic_stub(); | 1260     Code* stub = generic_stub(); | 
| 1229     if (state == UNINITIALIZED) { | 1261     if (state == UNINITIALIZED) { | 
| 1230       if (object->IsString() && key->IsNumber()) { | 1262       if (object->IsString() && key->IsNumber()) { | 
| 1231         stub = string_stub(); | 1263         stub = string_stub(); | 
| 1232       } else if (object->IsJSObject()) { | 1264       } else if (object->IsJSObject()) { | 
| 1233         Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1265         Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 
| 1234         if (receiver->HasExternalArrayElements()) { | 1266         if (receiver->HasExternalArrayElements()) { | 
| 1235           MaybeObject* probe = | 1267           MaybeObject* probe = | 
| 1236               StubCache::ComputeKeyedLoadOrStoreExternalArray(*receiver, | 1268               isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray( | 
| 1237                                                               false, | 1269                   *receiver, false, kNonStrictMode); | 
| 1238                                                               kNonStrictMode); |  | 
| 1239           stub = probe->IsFailure() ? | 1270           stub = probe->IsFailure() ? | 
| 1240               NULL : Code::cast(probe->ToObjectUnchecked()); | 1271               NULL : Code::cast(probe->ToObjectUnchecked()); | 
| 1241         } else if (receiver->HasIndexedInterceptor()) { | 1272         } else if (receiver->HasIndexedInterceptor()) { | 
| 1242           stub = indexed_interceptor_stub(); | 1273           stub = indexed_interceptor_stub(); | 
| 1243         } else if (key->IsSmi() && | 1274         } else if (key->IsSmi() && | 
| 1244                    receiver->map()->has_fast_elements()) { | 1275                    receiver->map()->has_fast_elements()) { | 
| 1245           MaybeObject* probe = | 1276           MaybeObject* probe = | 
| 1246               StubCache::ComputeKeyedLoadSpecialized(*receiver); | 1277               isolate()->stub_cache()->ComputeKeyedLoadSpecialized(*receiver); | 
| 1247           stub = probe->IsFailure() ? | 1278           stub = probe->IsFailure() ? | 
| 1248               NULL : Code::cast(probe->ToObjectUnchecked()); | 1279               NULL : Code::cast(probe->ToObjectUnchecked()); | 
| 1249         } | 1280         } | 
| 1250       } | 1281       } | 
| 1251     } | 1282     } | 
| 1252     if (stub != NULL) set_target(stub); | 1283     if (stub != NULL) set_target(stub); | 
| 1253 | 1284 | 
| 1254 #ifdef DEBUG | 1285 #ifdef DEBUG | 
| 1255     TraceIC("KeyedLoadIC", key, state, target()); | 1286     TraceIC("KeyedLoadIC", key, state, target()); | 
| 1256 #endif  // DEBUG | 1287 #endif  // DEBUG | 
| 1257 | 1288 | 
| 1258     // For JSObjects with fast elements that are not value wrappers | 1289     // For JSObjects with fast elements that are not value wrappers | 
| 1259     // and that do not have indexed interceptors, we initialize the | 1290     // and that do not have indexed interceptors, we initialize the | 
| 1260     // inlined fast case (if present) by patching the inlined map | 1291     // inlined fast case (if present) by patching the inlined map | 
| 1261     // check. | 1292     // check. | 
| 1262     if (object->IsJSObject() && | 1293     if (object->IsJSObject() && | 
| 1263         !object->IsJSValue() && | 1294         !object->IsJSValue() && | 
| 1264         !JSObject::cast(*object)->HasIndexedInterceptor() && | 1295         !JSObject::cast(*object)->HasIndexedInterceptor() && | 
| 1265         JSObject::cast(*object)->HasFastElements()) { | 1296         JSObject::cast(*object)->HasFastElements()) { | 
| 1266       Map* map = JSObject::cast(*object)->map(); | 1297       Map* map = JSObject::cast(*object)->map(); | 
| 1267       PatchInlinedLoad(address(), map); | 1298       PatchInlinedLoad(address(), map); | 
| 1268     } | 1299     } | 
| 1269   } | 1300   } | 
| 1270 | 1301 | 
| 1271   // Get the property. | 1302   // Get the property. | 
| 1272   return Runtime::GetObjectProperty(object, key); | 1303   return Runtime::GetObjectProperty(isolate(), object, key); | 
| 1273 } | 1304 } | 
| 1274 | 1305 | 
| 1275 | 1306 | 
| 1276 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, | 1307 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, | 
| 1277                                Handle<Object> object, Handle<String> name) { | 1308                                Handle<Object> object, Handle<String> name) { | 
| 1278   // Bail out if we didn't find a result. | 1309   // Bail out if we didn't find a result. | 
| 1279   if (!lookup->IsProperty() || !lookup->IsCacheable()) return; | 1310   if (!lookup->IsProperty() || !lookup->IsCacheable()) return; | 
| 1280 | 1311 | 
| 1281   if (!object->IsJSObject()) return; | 1312   if (!object->IsJSObject()) return; | 
| 1282   Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1313   Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 
| 1283 | 1314 | 
| 1284   if (HasNormalObjectsInPrototypeChain(lookup, *object)) return; | 1315   if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return; | 
| 1285 | 1316 | 
| 1286   // Compute the code stub for this load. | 1317   // Compute the code stub for this load. | 
| 1287   MaybeObject* maybe_code = NULL; | 1318   MaybeObject* maybe_code = NULL; | 
| 1288   Object* code; | 1319   Object* code; | 
| 1289 | 1320 | 
| 1290   if (state == UNINITIALIZED) { | 1321   if (state == UNINITIALIZED) { | 
| 1291     // This is the first time we execute this inline cache. | 1322     // This is the first time we execute this inline cache. | 
| 1292     // Set the target to the pre monomorphic stub to delay | 1323     // Set the target to the pre monomorphic stub to delay | 
| 1293     // setting the monomorphic state. | 1324     // setting the monomorphic state. | 
| 1294     maybe_code = pre_monomorphic_stub(); | 1325     maybe_code = pre_monomorphic_stub(); | 
| 1295   } else { | 1326   } else { | 
| 1296     // Compute a monomorphic stub. | 1327     // Compute a monomorphic stub. | 
| 1297     switch (lookup->type()) { | 1328     switch (lookup->type()) { | 
| 1298       case FIELD: { | 1329       case FIELD: { | 
| 1299         maybe_code = StubCache::ComputeKeyedLoadField(*name, *receiver, | 1330         maybe_code = isolate()->stub_cache()->ComputeKeyedLoadField( | 
| 1300                                                       lookup->holder(), | 1331             *name, *receiver, lookup->holder(), lookup->GetFieldIndex()); | 
| 1301                                                       lookup->GetFieldIndex()); |  | 
| 1302         break; | 1332         break; | 
| 1303       } | 1333       } | 
| 1304       case CONSTANT_FUNCTION: { | 1334       case CONSTANT_FUNCTION: { | 
| 1305         Object* constant = lookup->GetConstantFunction(); | 1335         Object* constant = lookup->GetConstantFunction(); | 
| 1306         maybe_code = StubCache::ComputeKeyedLoadConstant(*name, | 1336         maybe_code = isolate()->stub_cache()->ComputeKeyedLoadConstant( | 
| 1307                                                          *receiver, | 1337             *name, *receiver, lookup->holder(), constant); | 
| 1308                                                          lookup->holder(), |  | 
| 1309                                                          constant); |  | 
| 1310         break; | 1338         break; | 
| 1311       } | 1339       } | 
| 1312       case CALLBACKS: { | 1340       case CALLBACKS: { | 
| 1313         if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; | 1341         if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; | 
| 1314         AccessorInfo* callback = | 1342         AccessorInfo* callback = | 
| 1315             AccessorInfo::cast(lookup->GetCallbackObject()); | 1343             AccessorInfo::cast(lookup->GetCallbackObject()); | 
| 1316         if (v8::ToCData<Address>(callback->getter()) == 0) return; | 1344         if (v8::ToCData<Address>(callback->getter()) == 0) return; | 
| 1317         maybe_code = StubCache::ComputeKeyedLoadCallback(*name, | 1345         maybe_code = isolate()->stub_cache()->ComputeKeyedLoadCallback( | 
| 1318                                                          *receiver, | 1346             *name, *receiver, lookup->holder(), callback); | 
| 1319                                                          lookup->holder(), |  | 
| 1320                                                          callback); |  | 
| 1321         break; | 1347         break; | 
| 1322       } | 1348       } | 
| 1323       case INTERCEPTOR: { | 1349       case INTERCEPTOR: { | 
| 1324         ASSERT(HasInterceptorGetter(lookup->holder())); | 1350         ASSERT(HasInterceptorGetter(lookup->holder())); | 
| 1325         maybe_code = StubCache::ComputeKeyedLoadInterceptor(*name, *receiver, | 1351         maybe_code = isolate()->stub_cache()->ComputeKeyedLoadInterceptor( | 
| 1326                                                             lookup->holder()); | 1352             *name, *receiver, lookup->holder()); | 
| 1327         break; | 1353         break; | 
| 1328       } | 1354       } | 
| 1329       default: { | 1355       default: { | 
| 1330         // Always rewrite to the generic case so that we do not | 1356         // Always rewrite to the generic case so that we do not | 
| 1331         // repeatedly try to rewrite. | 1357         // repeatedly try to rewrite. | 
| 1332         maybe_code = generic_stub(); | 1358         maybe_code = generic_stub(); | 
| 1333         break; | 1359         break; | 
| 1334       } | 1360       } | 
| 1335     } | 1361     } | 
| 1336   } | 1362   } | 
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1392                             Handle<Object> value) { | 1418                             Handle<Object> value) { | 
| 1393   // If the object is undefined or null it's illegal to try to set any | 1419   // If the object is undefined or null it's illegal to try to set any | 
| 1394   // properties on it; throw a TypeError in that case. | 1420   // properties on it; throw a TypeError in that case. | 
| 1395   if (object->IsUndefined() || object->IsNull()) { | 1421   if (object->IsUndefined() || object->IsNull()) { | 
| 1396     return TypeError("non_object_property_store", object, name); | 1422     return TypeError("non_object_property_store", object, name); | 
| 1397   } | 1423   } | 
| 1398 | 1424 | 
| 1399   if (!object->IsJSObject()) { | 1425   if (!object->IsJSObject()) { | 
| 1400     // The length property of string values is read-only. Throw in strict mode. | 1426     // The length property of string values is read-only. Throw in strict mode. | 
| 1401     if (strict_mode == kStrictMode && object->IsString() && | 1427     if (strict_mode == kStrictMode && object->IsString() && | 
| 1402         name->Equals(Heap::length_symbol())) { | 1428         name->Equals(isolate()->heap()->length_symbol())) { | 
| 1403       return TypeError("strict_read_only_property", object, name); | 1429       return TypeError("strict_read_only_property", object, name); | 
| 1404     } | 1430     } | 
| 1405     // Ignore stores where the receiver is not a JSObject. | 1431     // Ignore stores where the receiver is not a JSObject. | 
| 1406     return *value; | 1432     return *value; | 
| 1407   } | 1433   } | 
| 1408 | 1434 | 
| 1409   Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1435   Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 
| 1410 | 1436 | 
| 1411   // Check if the given name is an array index. | 1437   // Check if the given name is an array index. | 
| 1412   uint32_t index; | 1438   uint32_t index; | 
| 1413   if (name->AsArrayIndex(&index)) { | 1439   if (name->AsArrayIndex(&index)) { | 
| 1414     HandleScope scope; | 1440     HandleScope scope(isolate()); | 
| 1415     Handle<Object> result = SetElement(receiver, index, value, strict_mode); | 1441     Handle<Object> result = SetElement(receiver, index, value, strict_mode); | 
| 1416     if (result.is_null()) return Failure::Exception(); | 1442     if (result.is_null()) return Failure::Exception(); | 
| 1417     return *value; | 1443     return *value; | 
| 1418   } | 1444   } | 
| 1419 | 1445 | 
| 1420   // Use specialized code for setting the length of arrays. | 1446   // Use specialized code for setting the length of arrays. | 
| 1421   if (receiver->IsJSArray() | 1447   if (receiver->IsJSArray() | 
| 1422       && name->Equals(Heap::length_symbol()) | 1448       && name->Equals(isolate()->heap()->length_symbol()) | 
| 1423       && receiver->AllowsSetElementsLength()) { | 1449       && receiver->AllowsSetElementsLength()) { | 
| 1424 #ifdef DEBUG | 1450 #ifdef DEBUG | 
| 1425     if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n"); | 1451     if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n"); | 
| 1426 #endif | 1452 #endif | 
| 1427     Builtins::Name target = (strict_mode == kStrictMode) | 1453     Builtins::Name target = (strict_mode == kStrictMode) | 
| 1428         ? Builtins::StoreIC_ArrayLength_Strict | 1454         ? Builtins::StoreIC_ArrayLength_Strict | 
| 1429         : Builtins::StoreIC_ArrayLength; | 1455         : Builtins::StoreIC_ArrayLength; | 
| 1430     set_target(Builtins::builtin(target)); | 1456     set_target(isolate()->builtins()->builtin(target)); | 
| 1431     return receiver->SetProperty(*name, *value, NONE, strict_mode); | 1457     return receiver->SetProperty(*name, *value, NONE, strict_mode); | 
| 1432   } | 1458   } | 
| 1433 | 1459 | 
| 1434   // Lookup the property locally in the receiver. | 1460   // Lookup the property locally in the receiver. | 
| 1435   if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) { | 1461   if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) { | 
| 1436     LookupResult lookup; | 1462     LookupResult lookup; | 
| 1437 | 1463 | 
| 1438     if (LookupForWrite(*receiver, *name, &lookup)) { | 1464     if (LookupForWrite(*receiver, *name, &lookup)) { | 
| 1439       bool can_be_inlined = | 1465       bool can_be_inlined = | 
| 1440           state == UNINITIALIZED && | 1466           state == UNINITIALIZED && | 
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1536   // current state. | 1562   // current state. | 
| 1537   PropertyType type = lookup->type(); | 1563   PropertyType type = lookup->type(); | 
| 1538 | 1564 | 
| 1539   // Compute the code stub for this store; used for rewriting to | 1565   // Compute the code stub for this store; used for rewriting to | 
| 1540   // monomorphic state and making sure that the code stub is in the | 1566   // monomorphic state and making sure that the code stub is in the | 
| 1541   // stub cache. | 1567   // stub cache. | 
| 1542   MaybeObject* maybe_code = NULL; | 1568   MaybeObject* maybe_code = NULL; | 
| 1543   Object* code = NULL; | 1569   Object* code = NULL; | 
| 1544   switch (type) { | 1570   switch (type) { | 
| 1545     case FIELD: { | 1571     case FIELD: { | 
| 1546       maybe_code = StubCache::ComputeStoreField( | 1572       maybe_code = isolate()->stub_cache()->ComputeStoreField( | 
| 1547           *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode); | 1573           *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode); | 
| 1548       break; | 1574       break; | 
| 1549     } | 1575     } | 
| 1550     case MAP_TRANSITION: { | 1576     case MAP_TRANSITION: { | 
| 1551       if (lookup->GetAttributes() != NONE) return; | 1577       if (lookup->GetAttributes() != NONE) return; | 
| 1552       HandleScope scope; | 1578       HandleScope scope(isolate()); | 
| 1553       ASSERT(type == MAP_TRANSITION); | 1579       ASSERT(type == MAP_TRANSITION); | 
| 1554       Handle<Map> transition(lookup->GetTransitionMap()); | 1580       Handle<Map> transition(lookup->GetTransitionMap()); | 
| 1555       int index = transition->PropertyIndexFor(*name); | 1581       int index = transition->PropertyIndexFor(*name); | 
| 1556       maybe_code = StubCache::ComputeStoreField( | 1582       maybe_code = isolate()->stub_cache()->ComputeStoreField( | 
| 1557           *name, *receiver, index, *transition, strict_mode); | 1583           *name, *receiver, index, *transition, strict_mode); | 
| 1558       break; | 1584       break; | 
| 1559     } | 1585     } | 
| 1560     case NORMAL: { | 1586     case NORMAL: { | 
| 1561       if (receiver->IsGlobalObject()) { | 1587       if (receiver->IsGlobalObject()) { | 
| 1562         // The stub generated for the global object picks the value directly | 1588         // The stub generated for the global object picks the value directly | 
| 1563         // from the property cell. So the property must be directly on the | 1589         // from the property cell. So the property must be directly on the | 
| 1564         // global object. | 1590         // global object. | 
| 1565         Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); | 1591         Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); | 
| 1566         JSGlobalPropertyCell* cell = | 1592         JSGlobalPropertyCell* cell = | 
| 1567             JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); | 1593             JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); | 
| 1568         maybe_code = StubCache::ComputeStoreGlobal( | 1594         maybe_code = isolate()->stub_cache()->ComputeStoreGlobal( | 
| 1569             *name, *global, cell, strict_mode); | 1595             *name, *global, cell, strict_mode); | 
| 1570       } else { | 1596       } else { | 
| 1571         if (lookup->holder() != *receiver) return; | 1597         if (lookup->holder() != *receiver) return; | 
| 1572         maybe_code = StubCache::ComputeStoreNormal(strict_mode); | 1598         maybe_code = isolate()->stub_cache()->ComputeStoreNormal(strict_mode); | 
| 1573       } | 1599       } | 
| 1574       break; | 1600       break; | 
| 1575     } | 1601     } | 
| 1576     case CALLBACKS: { | 1602     case CALLBACKS: { | 
| 1577       if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; | 1603       if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; | 
| 1578       AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); | 1604       AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); | 
| 1579       if (v8::ToCData<Address>(callback->setter()) == 0) return; | 1605       if (v8::ToCData<Address>(callback->setter()) == 0) return; | 
| 1580       maybe_code = StubCache::ComputeStoreCallback( | 1606       maybe_code = isolate()->stub_cache()->ComputeStoreCallback( | 
| 1581           *name, *receiver, callback, strict_mode); | 1607           *name, *receiver, callback, strict_mode); | 
| 1582       break; | 1608       break; | 
| 1583     } | 1609     } | 
| 1584     case INTERCEPTOR: { | 1610     case INTERCEPTOR: { | 
| 1585       ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined()); | 1611       ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined()); | 
| 1586       maybe_code = StubCache::ComputeStoreInterceptor( | 1612       maybe_code = isolate()->stub_cache()->ComputeStoreInterceptor( | 
| 1587           *name, *receiver, strict_mode); | 1613           *name, *receiver, strict_mode); | 
| 1588       break; | 1614       break; | 
| 1589     } | 1615     } | 
| 1590     default: | 1616     default: | 
| 1591       return; | 1617       return; | 
| 1592   } | 1618   } | 
| 1593 | 1619 | 
| 1594   // If we're unable to compute the stub (not enough memory left), we | 1620   // If we're unable to compute the stub (not enough memory left), we | 
| 1595   // simply avoid updating the caches. | 1621   // simply avoid updating the caches. | 
| 1596   if (maybe_code == NULL || !maybe_code->ToObject(&code)) return; | 1622   if (maybe_code == NULL || !maybe_code->ToObject(&code)) return; | 
| 1597 | 1623 | 
| 1598   // Patch the call site depending on the state of the cache. | 1624   // Patch the call site depending on the state of the cache. | 
| 1599   if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) { | 1625   if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) { | 
| 1600     set_target(Code::cast(code)); | 1626     set_target(Code::cast(code)); | 
| 1601   } else if (state == MONOMORPHIC) { | 1627   } else if (state == MONOMORPHIC) { | 
| 1602     // Only move to megamorphic if the target changes. | 1628     // Only move to megamorphic if the target changes. | 
| 1603     if (target() != Code::cast(code)) { | 1629     if (target() != Code::cast(code)) { | 
| 1604       set_target((strict_mode == kStrictMode) | 1630       set_target((strict_mode == kStrictMode) | 
| 1605                    ? megamorphic_stub_strict() | 1631                    ? megamorphic_stub_strict() | 
| 1606                    : megamorphic_stub()); | 1632                    : megamorphic_stub()); | 
| 1607     } | 1633     } | 
| 1608   } else if (state == MEGAMORPHIC) { | 1634   } else if (state == MEGAMORPHIC) { | 
| 1609     // Update the stub cache. | 1635     // Update the stub cache. | 
| 1610     StubCache::Set(*name, receiver->map(), Code::cast(code)); | 1636     isolate()->stub_cache()->Set(*name, | 
|  | 1637                                  receiver->map(), | 
|  | 1638                                  Code::cast(code)); | 
| 1611   } | 1639   } | 
| 1612 | 1640 | 
| 1613 #ifdef DEBUG | 1641 #ifdef DEBUG | 
| 1614   TraceIC("StoreIC", name, state, target()); | 1642   TraceIC("StoreIC", name, state, target()); | 
| 1615 #endif | 1643 #endif | 
| 1616 } | 1644 } | 
| 1617 | 1645 | 
| 1618 | 1646 | 
| 1619 MaybeObject* KeyedStoreIC::Store(State state, | 1647 MaybeObject* KeyedStoreIC::Store(State state, | 
| 1620                                  StrictModeFlag strict_mode, | 1648                                  StrictModeFlag strict_mode, | 
| 1621                                  Handle<Object> object, | 1649                                  Handle<Object> object, | 
| 1622                                  Handle<Object> key, | 1650                                  Handle<Object> key, | 
| 1623                                  Handle<Object> value) { | 1651                                  Handle<Object> value) { | 
| 1624   if (key->IsSymbol()) { | 1652   if (key->IsSymbol()) { | 
| 1625     Handle<String> name = Handle<String>::cast(key); | 1653     Handle<String> name = Handle<String>::cast(key); | 
| 1626 | 1654 | 
| 1627     // If the object is undefined or null it's illegal to try to set any | 1655     // If the object is undefined or null it's illegal to try to set any | 
| 1628     // properties on it; throw a TypeError in that case. | 1656     // properties on it; throw a TypeError in that case. | 
| 1629     if (object->IsUndefined() || object->IsNull()) { | 1657     if (object->IsUndefined() || object->IsNull()) { | 
| 1630       return TypeError("non_object_property_store", object, name); | 1658       return TypeError("non_object_property_store", object, name); | 
| 1631     } | 1659     } | 
| 1632 | 1660 | 
| 1633     // Ignore stores where the receiver is not a JSObject. | 1661     // Ignore stores where the receiver is not a JSObject. | 
| 1634     if (!object->IsJSObject()) return *value; | 1662     if (!object->IsJSObject()) return *value; | 
| 1635     Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1663     Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 
| 1636 | 1664 | 
| 1637     // Check if the given name is an array index. | 1665     // Check if the given name is an array index. | 
| 1638     uint32_t index; | 1666     uint32_t index; | 
| 1639     if (name->AsArrayIndex(&index)) { | 1667     if (name->AsArrayIndex(&index)) { | 
| 1640       HandleScope scope; | 1668       HandleScope scope(isolate()); | 
| 1641       Handle<Object> result = SetElement(receiver, index, value, strict_mode); | 1669       Handle<Object> result = SetElement(receiver, index, value, strict_mode); | 
| 1642       if (result.is_null()) return Failure::Exception(); | 1670       if (result.is_null()) return Failure::Exception(); | 
| 1643       return *value; | 1671       return *value; | 
| 1644     } | 1672     } | 
| 1645 | 1673 | 
| 1646     // Lookup the property locally in the receiver. | 1674     // Lookup the property locally in the receiver. | 
| 1647     LookupResult lookup; | 1675     LookupResult lookup; | 
| 1648     receiver->LocalLookup(*name, &lookup); | 1676     receiver->LocalLookup(*name, &lookup); | 
| 1649 | 1677 | 
| 1650     // Update inline cache and stub cache. | 1678     // Update inline cache and stub cache. | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
| 1662   ASSERT(!(use_ic && object->IsJSGlobalProxy())); | 1690   ASSERT(!(use_ic && object->IsJSGlobalProxy())); | 
| 1663 | 1691 | 
| 1664   if (use_ic) { | 1692   if (use_ic) { | 
| 1665     Code* stub = | 1693     Code* stub = | 
| 1666         (strict_mode == kStrictMode) ? generic_stub_strict() : generic_stub(); | 1694         (strict_mode == kStrictMode) ? generic_stub_strict() : generic_stub(); | 
| 1667     if (state == UNINITIALIZED) { | 1695     if (state == UNINITIALIZED) { | 
| 1668       if (object->IsJSObject()) { | 1696       if (object->IsJSObject()) { | 
| 1669         Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1697         Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 
| 1670         if (receiver->HasExternalArrayElements()) { | 1698         if (receiver->HasExternalArrayElements()) { | 
| 1671           MaybeObject* probe = | 1699           MaybeObject* probe = | 
| 1672               StubCache::ComputeKeyedLoadOrStoreExternalArray( | 1700               isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray( | 
| 1673                   *receiver, true, strict_mode); | 1701                   *receiver, true, strict_mode); | 
| 1674           stub = probe->IsFailure() ? | 1702           stub = probe->IsFailure() ? | 
| 1675               NULL : Code::cast(probe->ToObjectUnchecked()); | 1703               NULL : Code::cast(probe->ToObjectUnchecked()); | 
| 1676         } else if (key->IsSmi() && receiver->map()->has_fast_elements()) { | 1704         } else if (key->IsSmi() && receiver->map()->has_fast_elements()) { | 
| 1677           MaybeObject* probe = | 1705           MaybeObject* probe = | 
| 1678               StubCache::ComputeKeyedStoreSpecialized(*receiver, strict_mode); | 1706               isolate()->stub_cache()->ComputeKeyedStoreSpecialized( | 
|  | 1707                   *receiver, strict_mode); | 
| 1679           stub = probe->IsFailure() ? | 1708           stub = probe->IsFailure() ? | 
| 1680               NULL : Code::cast(probe->ToObjectUnchecked()); | 1709               NULL : Code::cast(probe->ToObjectUnchecked()); | 
| 1681         } | 1710         } | 
| 1682       } | 1711       } | 
| 1683     } | 1712     } | 
| 1684     if (stub != NULL) set_target(stub); | 1713     if (stub != NULL) set_target(stub); | 
| 1685   } | 1714   } | 
| 1686 | 1715 | 
| 1687   // Set the property. | 1716   // Set the property. | 
| 1688   return Runtime::SetObjectProperty(object, key, value, NONE, strict_mode); | 1717   return Runtime::SetObjectProperty( | 
|  | 1718       isolate(), object , key, value, NONE, strict_mode); | 
| 1689 } | 1719 } | 
| 1690 | 1720 | 
| 1691 | 1721 | 
| 1692 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, | 1722 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, | 
| 1693                                 State state, | 1723                                 State state, | 
| 1694                                 StrictModeFlag strict_mode, | 1724                                 StrictModeFlag strict_mode, | 
| 1695                                 Handle<JSObject> receiver, | 1725                                 Handle<JSObject> receiver, | 
| 1696                                 Handle<String> name, | 1726                                 Handle<String> name, | 
| 1697                                 Handle<Object> value) { | 1727                                 Handle<Object> value) { | 
| 1698   // Skip JSGlobalProxy. | 1728   // Skip JSGlobalProxy. | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
| 1711   PropertyType type = lookup->type(); | 1741   PropertyType type = lookup->type(); | 
| 1712 | 1742 | 
| 1713   // Compute the code stub for this store; used for rewriting to | 1743   // Compute the code stub for this store; used for rewriting to | 
| 1714   // monomorphic state and making sure that the code stub is in the | 1744   // monomorphic state and making sure that the code stub is in the | 
| 1715   // stub cache. | 1745   // stub cache. | 
| 1716   MaybeObject* maybe_code = NULL; | 1746   MaybeObject* maybe_code = NULL; | 
| 1717   Object* code = NULL; | 1747   Object* code = NULL; | 
| 1718 | 1748 | 
| 1719   switch (type) { | 1749   switch (type) { | 
| 1720     case FIELD: { | 1750     case FIELD: { | 
| 1721       maybe_code = StubCache::ComputeKeyedStoreField( | 1751       maybe_code = isolate()->stub_cache()->ComputeKeyedStoreField( | 
| 1722           *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode); | 1752           *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode); | 
| 1723       break; | 1753       break; | 
| 1724     } | 1754     } | 
| 1725     case MAP_TRANSITION: { | 1755     case MAP_TRANSITION: { | 
| 1726       if (lookup->GetAttributes() == NONE) { | 1756       if (lookup->GetAttributes() == NONE) { | 
| 1727         HandleScope scope; | 1757         HandleScope scope(isolate()); | 
| 1728         ASSERT(type == MAP_TRANSITION); | 1758         ASSERT(type == MAP_TRANSITION); | 
| 1729         Handle<Map> transition(lookup->GetTransitionMap()); | 1759         Handle<Map> transition(lookup->GetTransitionMap()); | 
| 1730         int index = transition->PropertyIndexFor(*name); | 1760         int index = transition->PropertyIndexFor(*name); | 
| 1731         maybe_code = StubCache::ComputeKeyedStoreField( | 1761         maybe_code = isolate()->stub_cache()->ComputeKeyedStoreField( | 
| 1732             *name, *receiver, index, *transition, strict_mode); | 1762             *name, *receiver, index, *transition, strict_mode); | 
| 1733         break; | 1763         break; | 
| 1734       } | 1764       } | 
| 1735       // fall through. | 1765       // fall through. | 
| 1736     } | 1766     } | 
| 1737     default: { | 1767     default: { | 
| 1738       // Always rewrite to the generic case so that we do not | 1768       // Always rewrite to the generic case so that we do not | 
| 1739       // repeatedly try to rewrite. | 1769       // repeatedly try to rewrite. | 
| 1740       maybe_code = (strict_mode == kStrictMode) | 1770       maybe_code = (strict_mode == kStrictMode) | 
| 1741           ? generic_stub_strict() | 1771           ? generic_stub_strict() | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
| 1762 #ifdef DEBUG | 1792 #ifdef DEBUG | 
| 1763   TraceIC("KeyedStoreIC", name, state, target()); | 1793   TraceIC("KeyedStoreIC", name, state, target()); | 
| 1764 #endif | 1794 #endif | 
| 1765 } | 1795 } | 
| 1766 | 1796 | 
| 1767 | 1797 | 
| 1768 // ---------------------------------------------------------------------------- | 1798 // ---------------------------------------------------------------------------- | 
| 1769 // Static IC stub generators. | 1799 // Static IC stub generators. | 
| 1770 // | 1800 // | 
| 1771 | 1801 | 
| 1772 static JSFunction* CompileFunction(JSFunction* function, | 1802 static JSFunction* CompileFunction(Isolate* isolate, | 
|  | 1803                                    JSFunction* function, | 
| 1773                                    InLoopFlag in_loop) { | 1804                                    InLoopFlag in_loop) { | 
| 1774   // Compile now with optimization. | 1805   // Compile now with optimization. | 
| 1775   HandleScope scope; | 1806   HandleScope scope(isolate); | 
| 1776   Handle<JSFunction> function_handle(function); | 1807   Handle<JSFunction> function_handle(function, isolate); | 
| 1777   if (in_loop == IN_LOOP) { | 1808   if (in_loop == IN_LOOP) { | 
| 1778     CompileLazyInLoop(function_handle, CLEAR_EXCEPTION); | 1809     CompileLazyInLoop(function_handle, CLEAR_EXCEPTION); | 
| 1779   } else { | 1810   } else { | 
| 1780     CompileLazy(function_handle, CLEAR_EXCEPTION); | 1811     CompileLazy(function_handle, CLEAR_EXCEPTION); | 
| 1781   } | 1812   } | 
| 1782   return *function_handle; | 1813   return *function_handle; | 
| 1783 } | 1814 } | 
| 1784 | 1815 | 
| 1785 | 1816 | 
| 1786 // Used from ic-<arch>.cc. | 1817 // Used from ic-<arch>.cc. | 
| 1787 MUST_USE_RESULT MaybeObject* CallIC_Miss(Arguments args) { | 1818 MUST_USE_RESULT MaybeObject* CallIC_Miss(RUNTIME_CALLING_CONVENTION) { | 
|  | 1819   RUNTIME_GET_ISOLATE; | 
| 1788   NoHandleAllocation na; | 1820   NoHandleAllocation na; | 
| 1789   ASSERT(args.length() == 2); | 1821   ASSERT(args.length() == 2); | 
| 1790   CallIC ic; | 1822   CallIC ic(isolate); | 
| 1791   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1823   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 
| 1792   Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | 1824   Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | 
| 1793   MaybeObject* maybe_result = ic.LoadFunction(state, | 1825   MaybeObject* maybe_result = ic.LoadFunction(state, | 
| 1794                                               extra_ic_state, | 1826                                               extra_ic_state, | 
| 1795                                               args.at<Object>(0), | 1827                                               args.at<Object>(0), | 
| 1796                                               args.at<String>(1)); | 1828                                               args.at<String>(1)); | 
| 1797   Object* result; | 1829   Object* result; | 
| 1798   if (!maybe_result->ToObject(&result)) return maybe_result; | 1830   if (!maybe_result->ToObject(&result)) return maybe_result; | 
| 1799 | 1831 | 
| 1800   // The first time the inline cache is updated may be the first time the | 1832   // The first time the inline cache is updated may be the first time the | 
| 1801   // function it references gets called.  If the function was lazily compiled | 1833   // function it references gets called.  If the function was lazily compiled | 
| 1802   // then the first call will trigger a compilation.  We check for this case | 1834   // then the first call will trigger a compilation.  We check for this case | 
| 1803   // and we do the compilation immediately, instead of waiting for the stub | 1835   // and we do the compilation immediately, instead of waiting for the stub | 
| 1804   // currently attached to the JSFunction object to trigger compilation.  We | 1836   // currently attached to the JSFunction object to trigger compilation.  We | 
| 1805   // do this in the case where we know that the inline cache is inside a loop, | 1837   // do this in the case where we know that the inline cache is inside a loop, | 
| 1806   // because then we know that we want to optimize the function. | 1838   // because then we know that we want to optimize the function. | 
| 1807   if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { | 1839   if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { | 
| 1808     return result; | 1840     return result; | 
| 1809   } | 1841   } | 
| 1810   return CompileFunction(JSFunction::cast(result), ic.target()->ic_in_loop()); | 1842   return CompileFunction(isolate, | 
|  | 1843                          JSFunction::cast(result), | 
|  | 1844                          ic.target()->ic_in_loop()); | 
| 1811 } | 1845 } | 
| 1812 | 1846 | 
| 1813 | 1847 | 
| 1814 // Used from ic-<arch>.cc. | 1848 // Used from ic-<arch>.cc. | 
| 1815 MUST_USE_RESULT MaybeObject* KeyedCallIC_Miss(Arguments args) { | 1849 MUST_USE_RESULT MaybeObject* KeyedCallIC_Miss(RUNTIME_CALLING_CONVENTION) { | 
|  | 1850   RUNTIME_GET_ISOLATE; | 
| 1816   NoHandleAllocation na; | 1851   NoHandleAllocation na; | 
| 1817   ASSERT(args.length() == 2); | 1852   ASSERT(args.length() == 2); | 
| 1818   KeyedCallIC ic; | 1853   KeyedCallIC ic(isolate); | 
| 1819   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1854   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 
| 1820   Object* result; | 1855   Object* result; | 
| 1821   { MaybeObject* maybe_result = | 1856   { MaybeObject* maybe_result = | 
| 1822       ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1)); | 1857       ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1)); | 
| 1823     if (!maybe_result->ToObject(&result)) return maybe_result; | 1858     if (!maybe_result->ToObject(&result)) return maybe_result; | 
| 1824   } | 1859   } | 
| 1825 | 1860 | 
| 1826   if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { | 1861   if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { | 
| 1827     return result; | 1862     return result; | 
| 1828   } | 1863   } | 
| 1829   return CompileFunction(JSFunction::cast(result), ic.target()->ic_in_loop()); | 1864   return CompileFunction(isolate, | 
|  | 1865                          JSFunction::cast(result), | 
|  | 1866                          ic.target()->ic_in_loop()); | 
| 1830 } | 1867 } | 
| 1831 | 1868 | 
| 1832 | 1869 | 
| 1833 // Used from ic-<arch>.cc. | 1870 // Used from ic-<arch>.cc. | 
| 1834 MUST_USE_RESULT MaybeObject* LoadIC_Miss(Arguments args) { | 1871 MUST_USE_RESULT MaybeObject* LoadIC_Miss(RUNTIME_CALLING_CONVENTION) { | 
|  | 1872   RUNTIME_GET_ISOLATE; | 
| 1835   NoHandleAllocation na; | 1873   NoHandleAllocation na; | 
| 1836   ASSERT(args.length() == 2); | 1874   ASSERT(args.length() == 2); | 
| 1837   LoadIC ic; | 1875   LoadIC ic(isolate); | 
| 1838   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1876   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 
| 1839   return ic.Load(state, args.at<Object>(0), args.at<String>(1)); | 1877   return ic.Load(state, args.at<Object>(0), args.at<String>(1)); | 
| 1840 } | 1878 } | 
| 1841 | 1879 | 
| 1842 | 1880 | 
| 1843 // Used from ic-<arch>.cc | 1881 // Used from ic-<arch>.cc | 
| 1844 MUST_USE_RESULT MaybeObject* KeyedLoadIC_Miss(Arguments args) { | 1882 MUST_USE_RESULT MaybeObject* KeyedLoadIC_Miss(RUNTIME_CALLING_CONVENTION) { | 
|  | 1883   RUNTIME_GET_ISOLATE; | 
| 1845   NoHandleAllocation na; | 1884   NoHandleAllocation na; | 
| 1846   ASSERT(args.length() == 2); | 1885   ASSERT(args.length() == 2); | 
| 1847   KeyedLoadIC ic; | 1886   KeyedLoadIC ic(isolate); | 
| 1848   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1887   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 
| 1849   return ic.Load(state, args.at<Object>(0), args.at<Object>(1)); | 1888   return ic.Load(state, args.at<Object>(0), args.at<Object>(1)); | 
| 1850 } | 1889 } | 
| 1851 | 1890 | 
| 1852 | 1891 | 
| 1853 // Used from ic-<arch>.cc. | 1892 // Used from ic-<arch>.cc. | 
| 1854 MUST_USE_RESULT MaybeObject* StoreIC_Miss(Arguments args) { | 1893 MUST_USE_RESULT MaybeObject* StoreIC_Miss(RUNTIME_CALLING_CONVENTION) { | 
|  | 1894   RUNTIME_GET_ISOLATE; | 
| 1855   NoHandleAllocation na; | 1895   NoHandleAllocation na; | 
| 1856   ASSERT(args.length() == 3); | 1896   ASSERT(args.length() == 3); | 
| 1857   StoreIC ic; | 1897   StoreIC ic(isolate); | 
| 1858   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1898   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 
| 1859   Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | 1899   Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | 
| 1860   return ic.Store(state, | 1900   return ic.Store(state, | 
| 1861                   static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), | 1901                   static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), | 
| 1862                   args.at<Object>(0), | 1902                   args.at<Object>(0), | 
| 1863                   args.at<String>(1), | 1903                   args.at<String>(1), | 
| 1864                   args.at<Object>(2)); | 1904                   args.at<Object>(2)); | 
| 1865 } | 1905 } | 
| 1866 | 1906 | 
| 1867 | 1907 | 
| 1868 MUST_USE_RESULT MaybeObject* StoreIC_ArrayLength(Arguments args) { | 1908 MUST_USE_RESULT MaybeObject* StoreIC_ArrayLength(RUNTIME_CALLING_CONVENTION) { | 
|  | 1909   RUNTIME_GET_ISOLATE; | 
| 1869   NoHandleAllocation nha; | 1910   NoHandleAllocation nha; | 
| 1870 | 1911 | 
| 1871   ASSERT(args.length() == 2); | 1912   ASSERT(args.length() == 2); | 
| 1872   JSObject* receiver = JSObject::cast(args[0]); | 1913   JSObject* receiver = JSObject::cast(args[0]); | 
| 1873   Object* len = args[1]; | 1914   Object* len = args[1]; | 
| 1874 | 1915 | 
| 1875   // The generated code should filter out non-Smis before we get here. | 1916   // The generated code should filter out non-Smis before we get here. | 
| 1876   ASSERT(len->IsSmi()); | 1917   ASSERT(len->IsSmi()); | 
| 1877 | 1918 | 
| 1878   Object* result; | 1919   Object* result; | 
| 1879   { MaybeObject* maybe_result = receiver->SetElementsLength(len); | 1920   { MaybeObject* maybe_result = receiver->SetElementsLength(len); | 
| 1880     if (!maybe_result->ToObject(&result)) return maybe_result; | 1921     if (!maybe_result->ToObject(&result)) return maybe_result; | 
| 1881   } | 1922   } | 
| 1882   return len; | 1923   return len; | 
| 1883 } | 1924 } | 
| 1884 | 1925 | 
| 1885 | 1926 | 
| 1886 // Extend storage is called in a store inline cache when | 1927 // Extend storage is called in a store inline cache when | 
| 1887 // it is necessary to extend the properties array of a | 1928 // it is necessary to extend the properties array of a | 
| 1888 // JSObject. | 1929 // JSObject. | 
| 1889 MUST_USE_RESULT MaybeObject* SharedStoreIC_ExtendStorage(Arguments args) { | 1930 MUST_USE_RESULT MaybeObject* SharedStoreIC_ExtendStorage( | 
|  | 1931     RUNTIME_CALLING_CONVENTION) { | 
|  | 1932   RUNTIME_GET_ISOLATE; | 
| 1890   NoHandleAllocation na; | 1933   NoHandleAllocation na; | 
| 1891   ASSERT(args.length() == 3); | 1934   ASSERT(args.length() == 3); | 
| 1892 | 1935 | 
| 1893   // Convert the parameters | 1936   // Convert the parameters | 
| 1894   JSObject* object = JSObject::cast(args[0]); | 1937   JSObject* object = JSObject::cast(args[0]); | 
| 1895   Map* transition = Map::cast(args[1]); | 1938   Map* transition = Map::cast(args[1]); | 
| 1896   Object* value = args[2]; | 1939   Object* value = args[2]; | 
| 1897 | 1940 | 
| 1898   // Check the object has run out out property space. | 1941   // Check the object has run out out property space. | 
| 1899   ASSERT(object->HasFastProperties()); | 1942   ASSERT(object->HasFastProperties()); | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
| 1913   // Set the new property value and do the map transition. | 1956   // Set the new property value and do the map transition. | 
| 1914   object->set_properties(new_storage); | 1957   object->set_properties(new_storage); | 
| 1915   object->set_map(transition); | 1958   object->set_map(transition); | 
| 1916 | 1959 | 
| 1917   // Return the stored value. | 1960   // Return the stored value. | 
| 1918   return value; | 1961   return value; | 
| 1919 } | 1962 } | 
| 1920 | 1963 | 
| 1921 | 1964 | 
| 1922 // Used from ic-<arch>.cc. | 1965 // Used from ic-<arch>.cc. | 
| 1923 MUST_USE_RESULT MaybeObject* KeyedStoreIC_Miss(Arguments args) { | 1966 MUST_USE_RESULT MaybeObject* KeyedStoreIC_Miss(RUNTIME_CALLING_CONVENTION) { | 
|  | 1967   RUNTIME_GET_ISOLATE; | 
| 1924   NoHandleAllocation na; | 1968   NoHandleAllocation na; | 
| 1925   ASSERT(args.length() == 3); | 1969   ASSERT(args.length() == 3); | 
| 1926   KeyedStoreIC ic; | 1970   KeyedStoreIC ic(isolate); | 
| 1927   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1971   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 
| 1928   Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | 1972   Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | 
| 1929   return ic.Store(state, | 1973   return ic.Store(state, | 
| 1930                   static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), | 1974                   static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), | 
| 1931                   args.at<Object>(0), | 1975                   args.at<Object>(0), | 
| 1932                   args.at<Object>(1), | 1976                   args.at<Object>(1), | 
| 1933                   args.at<Object>(2)); | 1977                   args.at<Object>(2)); | 
| 1934 } | 1978 } | 
| 1935 | 1979 | 
| 1936 | 1980 | 
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1986   } | 2030   } | 
| 1987 | 2031 | 
| 1988   return GENERIC; | 2032   return GENERIC; | 
| 1989 } | 2033 } | 
| 1990 | 2034 | 
| 1991 | 2035 | 
| 1992 // defined in code-stubs-<arch>.cc | 2036 // defined in code-stubs-<arch>.cc | 
| 1993 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info); | 2037 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info); | 
| 1994 | 2038 | 
| 1995 | 2039 | 
| 1996 MUST_USE_RESULT MaybeObject* BinaryOp_Patch(Arguments args) { | 2040 MUST_USE_RESULT MaybeObject* BinaryOp_Patch(RUNTIME_CALLING_CONVENTION) { | 
|  | 2041   RUNTIME_GET_ISOLATE; | 
| 1997   ASSERT(args.length() == 5); | 2042   ASSERT(args.length() == 5); | 
| 1998 | 2043 | 
| 1999   HandleScope scope; | 2044   HandleScope scope(isolate); | 
| 2000   Handle<Object> left = args.at<Object>(0); | 2045   Handle<Object> left = args.at<Object>(0); | 
| 2001   Handle<Object> right = args.at<Object>(1); | 2046   Handle<Object> right = args.at<Object>(1); | 
| 2002   int key = Smi::cast(args[2])->value(); | 2047   int key = Smi::cast(args[2])->value(); | 
| 2003   Token::Value op = static_cast<Token::Value>(Smi::cast(args[3])->value()); | 2048   Token::Value op = static_cast<Token::Value>(Smi::cast(args[3])->value()); | 
| 2004   BinaryOpIC::TypeInfo previous_type = | 2049   BinaryOpIC::TypeInfo previous_type = | 
| 2005       static_cast<BinaryOpIC::TypeInfo>(Smi::cast(args[4])->value()); | 2050       static_cast<BinaryOpIC::TypeInfo>(Smi::cast(args[4])->value()); | 
| 2006 | 2051 | 
| 2007   BinaryOpIC::TypeInfo type = BinaryOpIC::GetTypeInfo(*left, *right); | 2052   BinaryOpIC::TypeInfo type = BinaryOpIC::GetTypeInfo(*left, *right); | 
| 2008   Handle<Code> code = GetBinaryOpStub(key, type); | 2053   Handle<Code> code = GetBinaryOpStub(key, type); | 
| 2009   if (!code.is_null()) { | 2054   if (!code.is_null()) { | 
| 2010     BinaryOpIC ic; | 2055     BinaryOpIC ic(isolate); | 
| 2011     ic.patch(*code); | 2056     ic.patch(*code); | 
| 2012     if (FLAG_trace_ic) { | 2057     if (FLAG_trace_ic) { | 
| 2013       PrintF("[BinaryOpIC (%s->%s)#%s]\n", | 2058       PrintF("[BinaryOpIC (%s->%s)#%s]\n", | 
| 2014              BinaryOpIC::GetName(previous_type), | 2059              BinaryOpIC::GetName(previous_type), | 
| 2015              BinaryOpIC::GetName(type), | 2060              BinaryOpIC::GetName(type), | 
| 2016              Token::Name(op)); | 2061              Token::Name(op)); | 
| 2017     } | 2062     } | 
| 2018   } | 2063   } | 
| 2019 | 2064 | 
| 2020   Handle<JSBuiltinsObject> builtins = Top::builtins(); | 2065   Handle<JSBuiltinsObject> builtins = Handle<JSBuiltinsObject>( | 
|  | 2066       isolate->thread_local_top()->context_->builtins(), isolate); | 
| 2021   Object* builtin = NULL;  // Initialization calms down the compiler. | 2067   Object* builtin = NULL;  // Initialization calms down the compiler. | 
| 2022   switch (op) { | 2068   switch (op) { | 
| 2023     case Token::ADD: | 2069     case Token::ADD: | 
| 2024       builtin = builtins->javascript_builtin(Builtins::ADD); | 2070       builtin = builtins->javascript_builtin(Builtins::ADD); | 
| 2025       break; | 2071       break; | 
| 2026     case Token::SUB: | 2072     case Token::SUB: | 
| 2027       builtin = builtins->javascript_builtin(Builtins::SUB); | 2073       builtin = builtins->javascript_builtin(Builtins::SUB); | 
| 2028       break; | 2074       break; | 
| 2029     case Token::MUL: | 2075     case Token::MUL: | 
| 2030       builtin = builtins->javascript_builtin(Builtins::MUL); | 2076       builtin = builtins->javascript_builtin(Builtins::MUL); | 
| (...skipping 19 matching lines...) Expand all  Loading... | 
| 2050     case Token::SAR: | 2096     case Token::SAR: | 
| 2051       builtin = builtins->javascript_builtin(Builtins::SAR); | 2097       builtin = builtins->javascript_builtin(Builtins::SAR); | 
| 2052       break; | 2098       break; | 
| 2053     case Token::SHL: | 2099     case Token::SHL: | 
| 2054       builtin = builtins->javascript_builtin(Builtins::SHL); | 2100       builtin = builtins->javascript_builtin(Builtins::SHL); | 
| 2055       break; | 2101       break; | 
| 2056     default: | 2102     default: | 
| 2057       UNREACHABLE(); | 2103       UNREACHABLE(); | 
| 2058   } | 2104   } | 
| 2059 | 2105 | 
| 2060   Handle<JSFunction> builtin_function(JSFunction::cast(builtin)); | 2106   Handle<JSFunction> builtin_function(JSFunction::cast(builtin), | 
|  | 2107                                       isolate); | 
| 2061 | 2108 | 
| 2062   bool caught_exception; | 2109   bool caught_exception; | 
| 2063   Object** builtin_args[] = { right.location() }; | 2110   Object** builtin_args[] = { right.location() }; | 
| 2064   Handle<Object> result = Execution::Call(builtin_function, | 2111   Handle<Object> result = Execution::Call(builtin_function, | 
| 2065                                           left, | 2112                                           left, | 
| 2066                                           ARRAY_SIZE(builtin_args), | 2113                                           ARRAY_SIZE(builtin_args), | 
| 2067                                           builtin_args, | 2114                                           builtin_args, | 
| 2068                                           &caught_exception); | 2115                                           &caught_exception); | 
| 2069   if (caught_exception) { | 2116   if (caught_exception) { | 
| 2070     return Failure::Exception(); | 2117     return Failure::Exception(); | 
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2149 } | 2196 } | 
| 2150 | 2197 | 
| 2151 | 2198 | 
| 2152 // defined in code-stubs-<arch>.cc | 2199 // defined in code-stubs-<arch>.cc | 
| 2153 // Only needed to remove dependency of ic.cc on code-stubs-<arch>.h. | 2200 // Only needed to remove dependency of ic.cc on code-stubs-<arch>.h. | 
| 2154 Handle<Code> GetTypeRecordingBinaryOpStub(int key, | 2201 Handle<Code> GetTypeRecordingBinaryOpStub(int key, | 
| 2155                                           TRBinaryOpIC::TypeInfo type_info, | 2202                                           TRBinaryOpIC::TypeInfo type_info, | 
| 2156                                           TRBinaryOpIC::TypeInfo result_type); | 2203                                           TRBinaryOpIC::TypeInfo result_type); | 
| 2157 | 2204 | 
| 2158 | 2205 | 
| 2159 MaybeObject* TypeRecordingBinaryOp_Patch(Arguments args) { | 2206 MaybeObject* TypeRecordingBinaryOp_Patch(RUNTIME_CALLING_CONVENTION) { | 
|  | 2207   RUNTIME_GET_ISOLATE; | 
| 2160   ASSERT(args.length() == 5); | 2208   ASSERT(args.length() == 5); | 
| 2161 | 2209 | 
| 2162   HandleScope scope; | 2210   HandleScope scope(isolate); | 
| 2163   Handle<Object> left = args.at<Object>(0); | 2211   Handle<Object> left = args.at<Object>(0); | 
| 2164   Handle<Object> right = args.at<Object>(1); | 2212   Handle<Object> right = args.at<Object>(1); | 
| 2165   int key = Smi::cast(args[2])->value(); | 2213   int key = Smi::cast(args[2])->value(); | 
| 2166   Token::Value op = static_cast<Token::Value>(Smi::cast(args[3])->value()); | 2214   Token::Value op = static_cast<Token::Value>(Smi::cast(args[3])->value()); | 
| 2167   TRBinaryOpIC::TypeInfo previous_type = | 2215   TRBinaryOpIC::TypeInfo previous_type = | 
| 2168       static_cast<TRBinaryOpIC::TypeInfo>(Smi::cast(args[4])->value()); | 2216       static_cast<TRBinaryOpIC::TypeInfo>(Smi::cast(args[4])->value()); | 
| 2169 | 2217 | 
| 2170   TRBinaryOpIC::TypeInfo type = TRBinaryOpIC::GetTypeInfo(left, right); | 2218   TRBinaryOpIC::TypeInfo type = TRBinaryOpIC::GetTypeInfo(left, right); | 
| 2171   type = TRBinaryOpIC::JoinTypes(type, previous_type); | 2219   type = TRBinaryOpIC::JoinTypes(type, previous_type); | 
| 2172   TRBinaryOpIC::TypeInfo result_type = TRBinaryOpIC::UNINITIALIZED; | 2220   TRBinaryOpIC::TypeInfo result_type = TRBinaryOpIC::UNINITIALIZED; | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
| 2194 | 2242 | 
| 2195   Handle<Code> code = GetTypeRecordingBinaryOpStub(key, type, result_type); | 2243   Handle<Code> code = GetTypeRecordingBinaryOpStub(key, type, result_type); | 
| 2196   if (!code.is_null()) { | 2244   if (!code.is_null()) { | 
| 2197     if (FLAG_trace_ic) { | 2245     if (FLAG_trace_ic) { | 
| 2198       PrintF("[TypeRecordingBinaryOpIC (%s->(%s->%s))#%s]\n", | 2246       PrintF("[TypeRecordingBinaryOpIC (%s->(%s->%s))#%s]\n", | 
| 2199              TRBinaryOpIC::GetName(previous_type), | 2247              TRBinaryOpIC::GetName(previous_type), | 
| 2200              TRBinaryOpIC::GetName(type), | 2248              TRBinaryOpIC::GetName(type), | 
| 2201              TRBinaryOpIC::GetName(result_type), | 2249              TRBinaryOpIC::GetName(result_type), | 
| 2202              Token::Name(op)); | 2250              Token::Name(op)); | 
| 2203     } | 2251     } | 
| 2204     TRBinaryOpIC ic; | 2252     TRBinaryOpIC ic(isolate); | 
| 2205     ic.patch(*code); | 2253     ic.patch(*code); | 
| 2206 | 2254 | 
| 2207     // Activate inlined smi code. | 2255     // Activate inlined smi code. | 
| 2208     if (previous_type == TRBinaryOpIC::UNINITIALIZED) { | 2256     if (previous_type == TRBinaryOpIC::UNINITIALIZED) { | 
| 2209       PatchInlinedSmiCode(ic.address()); | 2257       PatchInlinedSmiCode(ic.address()); | 
| 2210     } | 2258     } | 
| 2211   } | 2259   } | 
| 2212 | 2260 | 
| 2213   Handle<JSBuiltinsObject> builtins = Top::builtins(); | 2261   Handle<JSBuiltinsObject> builtins = Handle<JSBuiltinsObject>( | 
|  | 2262       isolate->thread_local_top()->context_->builtins(), isolate); | 
| 2214   Object* builtin = NULL;  // Initialization calms down the compiler. | 2263   Object* builtin = NULL;  // Initialization calms down the compiler. | 
| 2215   switch (op) { | 2264   switch (op) { | 
| 2216     case Token::ADD: | 2265     case Token::ADD: | 
| 2217       builtin = builtins->javascript_builtin(Builtins::ADD); | 2266       builtin = builtins->javascript_builtin(Builtins::ADD); | 
| 2218       break; | 2267       break; | 
| 2219     case Token::SUB: | 2268     case Token::SUB: | 
| 2220       builtin = builtins->javascript_builtin(Builtins::SUB); | 2269       builtin = builtins->javascript_builtin(Builtins::SUB); | 
| 2221       break; | 2270       break; | 
| 2222     case Token::MUL: | 2271     case Token::MUL: | 
| 2223       builtin = builtins->javascript_builtin(Builtins::MUL); | 2272       builtin = builtins->javascript_builtin(Builtins::MUL); | 
| (...skipping 19 matching lines...) Expand all  Loading... | 
| 2243     case Token::SAR: | 2292     case Token::SAR: | 
| 2244       builtin = builtins->javascript_builtin(Builtins::SAR); | 2293       builtin = builtins->javascript_builtin(Builtins::SAR); | 
| 2245       break; | 2294       break; | 
| 2246     case Token::SHL: | 2295     case Token::SHL: | 
| 2247       builtin = builtins->javascript_builtin(Builtins::SHL); | 2296       builtin = builtins->javascript_builtin(Builtins::SHL); | 
| 2248       break; | 2297       break; | 
| 2249     default: | 2298     default: | 
| 2250       UNREACHABLE(); | 2299       UNREACHABLE(); | 
| 2251   } | 2300   } | 
| 2252 | 2301 | 
| 2253   Handle<JSFunction> builtin_function(JSFunction::cast(builtin)); | 2302   Handle<JSFunction> builtin_function(JSFunction::cast(builtin), isolate); | 
| 2254 | 2303 | 
| 2255   bool caught_exception; | 2304   bool caught_exception; | 
| 2256   Object** builtin_args[] = { right.location() }; | 2305   Object** builtin_args[] = { right.location() }; | 
| 2257   Handle<Object> result = Execution::Call(builtin_function, | 2306   Handle<Object> result = Execution::Call(builtin_function, | 
| 2258                                           left, | 2307                                           left, | 
| 2259                                           ARRAY_SIZE(builtin_args), | 2308                                           ARRAY_SIZE(builtin_args), | 
| 2260                                           builtin_args, | 2309                                           builtin_args, | 
| 2261                                           &caught_exception); | 2310                                           &caught_exception); | 
| 2262   if (caught_exception) { | 2311   if (caught_exception) { | 
| 2263     return Failure::Exception(); | 2312     return Failure::Exception(); | 
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2303   if ((state == UNINITIALIZED || (state == SMIS && has_inlined_smi_code)) && | 2352   if ((state == UNINITIALIZED || (state == SMIS && has_inlined_smi_code)) && | 
| 2304       x->IsNumber() && y->IsNumber()) return HEAP_NUMBERS; | 2353       x->IsNumber() && y->IsNumber()) return HEAP_NUMBERS; | 
| 2305   if (op_ != Token::EQ && op_ != Token::EQ_STRICT) return GENERIC; | 2354   if (op_ != Token::EQ && op_ != Token::EQ_STRICT) return GENERIC; | 
| 2306   if (state == UNINITIALIZED && | 2355   if (state == UNINITIALIZED && | 
| 2307       x->IsJSObject() && y->IsJSObject()) return OBJECTS; | 2356       x->IsJSObject() && y->IsJSObject()) return OBJECTS; | 
| 2308   return GENERIC; | 2357   return GENERIC; | 
| 2309 } | 2358 } | 
| 2310 | 2359 | 
| 2311 | 2360 | 
| 2312 // Used from ic_<arch>.cc. | 2361 // Used from ic_<arch>.cc. | 
| 2313 Code* CompareIC_Miss(Arguments args) { | 2362 Code* CompareIC_Miss(RUNTIME_CALLING_CONVENTION) { | 
|  | 2363   RUNTIME_GET_ISOLATE; | 
| 2314   NoHandleAllocation na; | 2364   NoHandleAllocation na; | 
| 2315   ASSERT(args.length() == 3); | 2365   ASSERT(args.length() == 3); | 
| 2316   CompareIC ic(static_cast<Token::Value>(Smi::cast(args[2])->value())); | 2366   CompareIC ic(isolate, static_cast<Token::Value>(Smi::cast(args[2])->value())); | 
| 2317   ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); | 2367   ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); | 
| 2318   return ic.target(); | 2368   return ic.target(); | 
| 2319 } | 2369 } | 
| 2320 | 2370 | 
| 2321 | 2371 | 
| 2322 static Address IC_utilities[] = { | 2372 static const Address IC_utilities[] = { | 
| 2323 #define ADDR(name) FUNCTION_ADDR(name), | 2373 #define ADDR(name) FUNCTION_ADDR(name), | 
| 2324     IC_UTIL_LIST(ADDR) | 2374     IC_UTIL_LIST(ADDR) | 
| 2325     NULL | 2375     NULL | 
| 2326 #undef ADDR | 2376 #undef ADDR | 
| 2327 }; | 2377 }; | 
| 2328 | 2378 | 
| 2329 | 2379 | 
| 2330 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2380 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 
| 2331   return IC_utilities[id]; | 2381   return IC_utilities[id]; | 
| 2332 } | 2382 } | 
| 2333 | 2383 | 
| 2334 | 2384 | 
| 2335 } }  // namespace v8::internal | 2385 } }  // namespace v8::internal | 
| OLD | NEW | 
|---|