| 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 134 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 145   // Decide whether the inline cache failed because of changes to the | 145   // Decide whether the inline cache failed because of changes to the | 
| 146   // receiver itself or changes to one of its prototypes. | 146   // receiver itself or changes to one of its prototypes. | 
| 147   // | 147   // | 
| 148   // If there are changes to the receiver itself, the map of the | 148   // If there are changes to the receiver itself, the map of the | 
| 149   // receiver will have changed and the current target will not be in | 149   // receiver will have changed and the current target will not be in | 
| 150   // the receiver map's code cache.  Therefore, if the current target | 150   // the receiver map's code cache.  Therefore, if the current target | 
| 151   // is in the receiver map's code cache, the inline cache failed due | 151   // is in the receiver map's code cache, the inline cache failed due | 
| 152   // to prototype check failure. | 152   // to prototype check failure. | 
| 153   int index = map->IndexInCodeCache(name, target); | 153   int index = map->IndexInCodeCache(name, target); | 
| 154   if (index >= 0) { | 154   if (index >= 0) { | 
| 155     // For keyed load/store, the most likely cause of cache failure is | 155     // For keyed load/store/call, the most likely cause of cache failure is | 
| 156     // that the key has changed.  We do not distinguish between | 156     // that the key has changed.  We do not distinguish between | 
| 157     // prototype and non-prototype failures for keyed access. | 157     // prototype and non-prototype failures for keyed access. | 
| 158     Code::Kind kind = target->kind(); | 158     Code::Kind kind = target->kind(); | 
| 159     if (kind == Code::KEYED_LOAD_IC || kind == Code::KEYED_STORE_IC) { | 159     if (kind == Code::KEYED_LOAD_IC || | 
|  | 160         kind == Code::KEYED_STORE_IC || | 
|  | 161         kind == Code::KEYED_CALL_IC) { | 
| 160       return MONOMORPHIC; | 162       return MONOMORPHIC; | 
| 161     } | 163     } | 
| 162 | 164 | 
| 163     // Remove the target from the code cache to avoid hitting the same | 165     // Remove the target from the code cache to avoid hitting the same | 
| 164     // invalid stub again. | 166     // invalid stub again. | 
| 165     map->RemoveFromCodeCache(String::cast(name), target, index); | 167     map->RemoveFromCodeCache(String::cast(name), target, index); | 
| 166 | 168 | 
| 167     return MONOMORPHIC_PROTOTYPE_FAILURE; | 169     return MONOMORPHIC_PROTOTYPE_FAILURE; | 
| 168   } | 170   } | 
| 169 | 171 | 
| (...skipping 19 matching lines...) Expand all  Loading... | 
| 189     RelocInfo* info = it.rinfo(); | 191     RelocInfo* info = it.rinfo(); | 
| 190     if (info->pc() == addr) return info->rmode(); | 192     if (info->pc() == addr) return info->rmode(); | 
| 191   } | 193   } | 
| 192   UNREACHABLE(); | 194   UNREACHABLE(); | 
| 193   return RelocInfo::NONE; | 195   return RelocInfo::NONE; | 
| 194 } | 196 } | 
| 195 | 197 | 
| 196 | 198 | 
| 197 Failure* IC::TypeError(const char* type, | 199 Failure* IC::TypeError(const char* type, | 
| 198                        Handle<Object> object, | 200                        Handle<Object> object, | 
| 199                        Handle<String> name) { | 201                        Handle<Object> key) { | 
| 200   HandleScope scope; | 202   HandleScope scope; | 
| 201   Handle<Object> args[2] = { name, object }; | 203   Handle<Object> args[2] = { key, object }; | 
| 202   Handle<Object> error = Factory::NewTypeError(type, HandleVector(args, 2)); | 204   Handle<Object> error = Factory::NewTypeError(type, HandleVector(args, 2)); | 
| 203   return Top::Throw(*error); | 205   return Top::Throw(*error); | 
| 204 } | 206 } | 
| 205 | 207 | 
| 206 | 208 | 
| 207 Failure* IC::ReferenceError(const char* type, Handle<String> name) { | 209 Failure* IC::ReferenceError(const char* type, Handle<String> name) { | 
| 208   HandleScope scope; | 210   HandleScope scope; | 
| 209   Handle<Object> error = | 211   Handle<Object> error = | 
| 210       Factory::NewReferenceError(type, HandleVector(&name, 1)); | 212       Factory::NewReferenceError(type, HandleVector(&name, 1)); | 
| 211   return Top::Throw(*error); | 213   return Top::Throw(*error); | 
| 212 } | 214 } | 
| 213 | 215 | 
| 214 | 216 | 
| 215 void IC::Clear(Address address) { | 217 void IC::Clear(Address address) { | 
| 216   Code* target = GetTargetAtAddress(address); | 218   Code* target = GetTargetAtAddress(address); | 
| 217 | 219 | 
| 218   // Don't clear debug break inline cache as it will remove the break point. | 220   // Don't clear debug break inline cache as it will remove the break point. | 
| 219   if (target->ic_state() == DEBUG_BREAK) return; | 221   if (target->ic_state() == DEBUG_BREAK) return; | 
| 220 | 222 | 
| 221   switch (target->kind()) { | 223   switch (target->kind()) { | 
| 222     case Code::LOAD_IC: return LoadIC::Clear(address, target); | 224     case Code::LOAD_IC: return LoadIC::Clear(address, target); | 
| 223     case Code::KEYED_LOAD_IC: return KeyedLoadIC::Clear(address, target); | 225     case Code::KEYED_LOAD_IC: return KeyedLoadIC::Clear(address, target); | 
| 224     case Code::STORE_IC: return StoreIC::Clear(address, target); | 226     case Code::STORE_IC: return StoreIC::Clear(address, target); | 
| 225     case Code::KEYED_STORE_IC: return KeyedStoreIC::Clear(address, target); | 227     case Code::KEYED_STORE_IC: return KeyedStoreIC::Clear(address, target); | 
| 226     case Code::CALL_IC: return CallIC::Clear(address, target); | 228     case Code::CALL_IC: return CallIC::Clear(address, target); | 
|  | 229     case Code::KEYED_CALL_IC:  return KeyedCallIC::Clear(address, target); | 
| 227     case Code::BINARY_OP_IC: return;  // Clearing these is tricky and does not | 230     case Code::BINARY_OP_IC: return;  // Clearing these is tricky and does not | 
| 228                                       // make any performance difference. | 231                                       // make any performance difference. | 
| 229     default: UNREACHABLE(); | 232     default: UNREACHABLE(); | 
| 230   } | 233   } | 
| 231 } | 234 } | 
| 232 | 235 | 
| 233 | 236 | 
| 234 void CallIC::Clear(Address address, Code* target) { | 237 void CallICBase::Clear(Address address, Code* target) { | 
| 235   State state = target->ic_state(); | 238   State state = target->ic_state(); | 
| 236   InLoopFlag in_loop = target->ic_in_loop(); |  | 
| 237   if (state == UNINITIALIZED) return; | 239   if (state == UNINITIALIZED) return; | 
| 238   Code* code = | 240   Code* code = | 
| 239       StubCache::FindCallInitialize(target->arguments_count(), in_loop); | 241       StubCache::FindCallInitialize(target->arguments_count(), | 
|  | 242                                     target->ic_in_loop(), | 
|  | 243                                     target->kind()); | 
| 240   SetTargetAtAddress(address, code); | 244   SetTargetAtAddress(address, code); | 
| 241 } | 245 } | 
| 242 | 246 | 
| 243 | 247 | 
| 244 void KeyedLoadIC::Clear(Address address, Code* target) { | 248 void KeyedLoadIC::Clear(Address address, Code* target) { | 
| 245   if (target->ic_state() == UNINITIALIZED) return; | 249   if (target->ic_state() == UNINITIALIZED) return; | 
| 246   // Make sure to also clear the map used in inline fast cases.  If we | 250   // Make sure to also clear the map used in inline fast cases.  If we | 
| 247   // do not clear these maps, cached code can keep objects alive | 251   // do not clear these maps, cached code can keep objects alive | 
| 248   // through the embedded maps. | 252   // through the embedded maps. | 
| 249   ClearInlinedVersion(address); | 253   ClearInlinedVersion(address); | 
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 357     if (proto->IsNull()) { | 361     if (proto->IsNull()) { | 
| 358       lookup->NotFound(); | 362       lookup->NotFound(); | 
| 359       return; | 363       return; | 
| 360     } | 364     } | 
| 361 | 365 | 
| 362     object = proto; | 366     object = proto; | 
| 363   } | 367   } | 
| 364 } | 368 } | 
| 365 | 369 | 
| 366 | 370 | 
| 367 Object* CallIC::TryCallAsFunction(Object* object) { | 371 Object* CallICBase::TryCallAsFunction(Object* object) { | 
| 368   HandleScope scope; | 372   HandleScope scope; | 
| 369   Handle<Object> target(object); | 373   Handle<Object> target(object); | 
| 370   Handle<Object> delegate = Execution::GetFunctionDelegate(target); | 374   Handle<Object> delegate = Execution::GetFunctionDelegate(target); | 
| 371 | 375 | 
| 372   if (delegate->IsJSFunction()) { | 376   if (delegate->IsJSFunction()) { | 
| 373     // Patch the receiver and use the delegate as the function to | 377     // Patch the receiver and use the delegate as the function to | 
| 374     // invoke. This is used for invoking objects as if they were | 378     // invoke. This is used for invoking objects as if they were | 
| 375     // functions. | 379     // functions. | 
| 376     const int argc = this->target()->arguments_count(); | 380     const int argc = this->target()->arguments_count(); | 
| 377     StackFrameLocator locator; | 381     StackFrameLocator locator; | 
| 378     JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 382     JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 
| 379     int index = frame->ComputeExpressionsCount() - (argc + 1); | 383     int index = frame->ComputeExpressionsCount() - (argc + 1); | 
| 380     frame->SetExpression(index, *target); | 384     frame->SetExpression(index, *target); | 
| 381   } | 385   } | 
| 382 | 386 | 
| 383   return *delegate; | 387   return *delegate; | 
| 384 } | 388 } | 
| 385 | 389 | 
| 386 void CallIC::ReceiverToObject(Handle<Object> object) { | 390 void CallICBase::ReceiverToObject(Handle<Object> object) { | 
| 387   HandleScope scope; | 391   HandleScope scope; | 
| 388   Handle<Object> receiver(object); | 392   Handle<Object> receiver(object); | 
| 389 | 393 | 
| 390   // Change the receiver to the result of calling ToObject on it. | 394   // Change the receiver to the result of calling ToObject on it. | 
| 391   const int argc = this->target()->arguments_count(); | 395   const int argc = this->target()->arguments_count(); | 
| 392   StackFrameLocator locator; | 396   StackFrameLocator locator; | 
| 393   JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 397   JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 
| 394   int index = frame->ComputeExpressionsCount() - (argc + 1); | 398   int index = frame->ComputeExpressionsCount() - (argc + 1); | 
| 395   frame->SetExpression(index, *Factory::ToObject(object)); | 399   frame->SetExpression(index, *Factory::ToObject(object)); | 
| 396 } | 400 } | 
| 397 | 401 | 
| 398 | 402 | 
| 399 Object* CallIC::LoadFunction(State state, | 403 Object* CallICBase::LoadFunction(State state, | 
| 400                              Handle<Object> object, | 404                                  Handle<Object> object, | 
| 401                              Handle<String> name) { | 405                                  Handle<String> name) { | 
| 402   // If the object is undefined or null it's illegal to try to get any | 406   // If the object is undefined or null it's illegal to try to get any | 
| 403   // of its properties; throw a TypeError in that case. | 407   // of its properties; throw a TypeError in that case. | 
| 404   if (object->IsUndefined() || object->IsNull()) { | 408   if (object->IsUndefined() || object->IsNull()) { | 
| 405     return TypeError("non_object_property_call", object, name); | 409     return TypeError("non_object_property_call", object, name); | 
| 406   } | 410   } | 
| 407 | 411 | 
| 408   if (object->IsString() || object->IsNumber() || object->IsBoolean()) { | 412   if (object->IsString() || object->IsNumber() || object->IsBoolean()) { | 
| 409     ReceiverToObject(object); | 413     ReceiverToObject(object); | 
| 410   } | 414   } | 
| 411 | 415 | 
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 474     return result; | 478     return result; | 
| 475   } | 479   } | 
| 476 | 480 | 
| 477   // Try to find a suitable function delegate for the object at hand. | 481   // Try to find a suitable function delegate for the object at hand. | 
| 478   result = TryCallAsFunction(result); | 482   result = TryCallAsFunction(result); | 
| 479   return result->IsJSFunction() ? | 483   return result->IsJSFunction() ? | 
| 480       result : TypeError("property_not_function", object, name); | 484       result : TypeError("property_not_function", object, name); | 
| 481 } | 485 } | 
| 482 | 486 | 
| 483 | 487 | 
| 484 void CallIC::UpdateCaches(LookupResult* lookup, | 488 void CallICBase::UpdateCaches(LookupResult* lookup, | 
| 485                           State state, | 489                           State state, | 
| 486                           Handle<Object> object, | 490                           Handle<Object> object, | 
| 487                           Handle<String> name) { | 491                           Handle<String> name) { | 
| 488   // Bail out if we didn't find a result. | 492   // Bail out if we didn't find a result. | 
| 489   if (!lookup->IsProperty() || !lookup->IsCacheable()) return; | 493   if (!lookup->IsProperty() || !lookup->IsCacheable()) return; | 
| 490 | 494 | 
| 491   // Compute the number of arguments. | 495   // Compute the number of arguments. | 
| 492   int argc = target()->arguments_count(); | 496   int argc = target()->arguments_count(); | 
| 493   InLoopFlag in_loop = target()->ic_in_loop(); | 497   InLoopFlag in_loop = target()->ic_in_loop(); | 
| 494   Object* code = NULL; | 498   Object* code = NULL; | 
| 495 | 499 | 
| 496   if (state == UNINITIALIZED) { | 500   if (state == UNINITIALIZED) { | 
| 497     // This is the first time we execute this inline cache. | 501     // This is the first time we execute this inline cache. | 
| 498     // Set the target to the pre monomorphic stub to delay | 502     // Set the target to the pre monomorphic stub to delay | 
| 499     // setting the monomorphic state. | 503     // setting the monomorphic state. | 
| 500     code = StubCache::ComputeCallPreMonomorphic(argc, in_loop); | 504     code = StubCache::ComputeCallPreMonomorphic(argc, in_loop, kind_); | 
| 501   } else if (state == MONOMORPHIC) { | 505   } else if (state == MONOMORPHIC) { | 
| 502     code = StubCache::ComputeCallMegamorphic(argc, in_loop); | 506     code = StubCache::ComputeCallMegamorphic(argc, in_loop, kind_); | 
| 503   } else { | 507   } else { | 
| 504     // Compute monomorphic stub. | 508     // Compute monomorphic stub. | 
| 505     switch (lookup->type()) { | 509     switch (lookup->type()) { | 
| 506       case FIELD: { | 510       case FIELD: { | 
| 507         int index = lookup->GetFieldIndex(); | 511         int index = lookup->GetFieldIndex(); | 
| 508         code = StubCache::ComputeCallField(argc, in_loop, *name, *object, | 512         code = StubCache::ComputeCallField(argc, | 
| 509                                            lookup->holder(), index); | 513                                            in_loop, | 
|  | 514                                            kind_, | 
|  | 515                                            *name, | 
|  | 516                                            *object, | 
|  | 517                                            lookup->holder(), | 
|  | 518                                            index); | 
| 510         break; | 519         break; | 
| 511       } | 520       } | 
| 512       case CONSTANT_FUNCTION: { | 521       case CONSTANT_FUNCTION: { | 
| 513         // Get the constant function and compute the code stub for this | 522         // Get the constant function and compute the code stub for this | 
| 514         // call; used for rewriting to monomorphic state and making sure | 523         // call; used for rewriting to monomorphic state and making sure | 
| 515         // that the code stub is in the stub cache. | 524         // that the code stub is in the stub cache. | 
| 516         JSFunction* function = lookup->GetConstantFunction(); | 525         JSFunction* function = lookup->GetConstantFunction(); | 
| 517         code = StubCache::ComputeCallConstant(argc, in_loop, *name, *object, | 526         code = StubCache::ComputeCallConstant(argc, | 
| 518                                               lookup->holder(), function); | 527                                               in_loop, | 
|  | 528                                               kind_, | 
|  | 529                                               *name, | 
|  | 530                                               *object, | 
|  | 531                                               lookup->holder(), | 
|  | 532                                               function); | 
| 519         break; | 533         break; | 
| 520       } | 534       } | 
| 521       case NORMAL: { | 535       case NORMAL: { | 
| 522         if (!object->IsJSObject()) return; | 536         if (!object->IsJSObject()) return; | 
| 523         Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 537         Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 
| 524 | 538 | 
| 525         if (lookup->holder()->IsGlobalObject()) { | 539         if (lookup->holder()->IsGlobalObject()) { | 
| 526           GlobalObject* global = GlobalObject::cast(lookup->holder()); | 540           GlobalObject* global = GlobalObject::cast(lookup->holder()); | 
| 527           JSGlobalPropertyCell* cell = | 541           JSGlobalPropertyCell* cell = | 
| 528               JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); | 542               JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); | 
| 529           if (!cell->value()->IsJSFunction()) return; | 543           if (!cell->value()->IsJSFunction()) return; | 
| 530           JSFunction* function = JSFunction::cast(cell->value()); | 544           JSFunction* function = JSFunction::cast(cell->value()); | 
| 531           code = StubCache::ComputeCallGlobal(argc, | 545           code = StubCache::ComputeCallGlobal(argc, | 
| 532                                               in_loop, | 546                                               in_loop, | 
|  | 547                                               kind_, | 
| 533                                               *name, | 548                                               *name, | 
| 534                                               *receiver, | 549                                               *receiver, | 
| 535                                               global, | 550                                               global, | 
| 536                                               cell, | 551                                               cell, | 
| 537                                               function); | 552                                               function); | 
| 538         } else { | 553         } else { | 
| 539           // There is only one shared stub for calling normalized | 554           // There is only one shared stub for calling normalized | 
| 540           // properties. It does not traverse the prototype chain, so the | 555           // properties. It does not traverse the prototype chain, so the | 
| 541           // property must be found in the receiver for the stub to be | 556           // property must be found in the receiver for the stub to be | 
| 542           // applicable. | 557           // applicable. | 
| 543           if (lookup->holder() != *receiver) return; | 558           if (lookup->holder() != *receiver) return; | 
| 544           code = StubCache::ComputeCallNormal(argc, in_loop, *name, *receiver); | 559           code = StubCache::ComputeCallNormal(argc, | 
|  | 560                                               in_loop, | 
|  | 561                                               kind_, | 
|  | 562                                               *name, | 
|  | 563                                               *receiver); | 
| 545         } | 564         } | 
| 546         break; | 565         break; | 
| 547       } | 566       } | 
| 548       case INTERCEPTOR: { | 567       case INTERCEPTOR: { | 
| 549         ASSERT(HasInterceptorGetter(lookup->holder())); | 568         ASSERT(HasInterceptorGetter(lookup->holder())); | 
| 550         code = StubCache::ComputeCallInterceptor(argc, *name, *object, | 569         code = StubCache::ComputeCallInterceptor(argc, | 
|  | 570                                                  kind_, | 
|  | 571                                                  *name, | 
|  | 572                                                  *object, | 
| 551                                                  lookup->holder()); | 573                                                  lookup->holder()); | 
| 552         break; | 574         break; | 
| 553       } | 575       } | 
| 554       default: | 576       default: | 
| 555         return; | 577         return; | 
| 556     } | 578     } | 
| 557   } | 579   } | 
| 558 | 580 | 
| 559   // If we're unable to compute the stub (not enough memory left), we | 581   // If we're unable to compute the stub (not enough memory left), we | 
| 560   // simply avoid updating the caches. | 582   // simply avoid updating the caches. | 
| 561   if (code == NULL || code->IsFailure()) return; | 583   if (code == NULL || code->IsFailure()) return; | 
| 562 | 584 | 
| 563   // Patch the call site depending on the state of the cache. | 585   // Patch the call site depending on the state of the cache. | 
| 564   if (state == UNINITIALIZED || | 586   if (state == UNINITIALIZED || | 
| 565       state == PREMONOMORPHIC || | 587       state == PREMONOMORPHIC || | 
| 566       state == MONOMORPHIC || | 588       state == MONOMORPHIC || | 
| 567       state == MONOMORPHIC_PROTOTYPE_FAILURE) { | 589       state == MONOMORPHIC_PROTOTYPE_FAILURE) { | 
| 568     set_target(Code::cast(code)); | 590     set_target(Code::cast(code)); | 
| 569   } | 591   } | 
| 570 | 592 | 
| 571 #ifdef DEBUG | 593 #ifdef DEBUG | 
| 572   TraceIC("CallIC", name, state, target(), in_loop ? " (in-loop)" : ""); | 594   TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", | 
|  | 595       name, state, target(), in_loop ? " (in-loop)" : ""); | 
| 573 #endif | 596 #endif | 
| 574 } | 597 } | 
| 575 | 598 | 
| 576 | 599 | 
|  | 600 Object* KeyedCallIC::LoadFunction(State state, | 
|  | 601                                   Handle<Object> object, | 
|  | 602                                   Handle<Object> key) { | 
|  | 603   if (key->IsSymbol()) { | 
|  | 604     return CallICBase::LoadFunction(state, object, Handle<String>::cast(key)); | 
|  | 605   } | 
|  | 606 | 
|  | 607   if (object->IsUndefined() || object->IsNull()) { | 
|  | 608     return TypeError("non_object_property_call", object, key); | 
|  | 609   } | 
|  | 610 | 
|  | 611   if (object->IsString() || object->IsNumber() || object->IsBoolean()) { | 
|  | 612     ReceiverToObject(object); | 
|  | 613   } else { | 
|  | 614     if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) { | 
|  | 615       int argc = target()->arguments_count(); | 
|  | 616       InLoopFlag in_loop = target()->ic_in_loop(); | 
|  | 617       Object* code = StubCache::ComputeCallMegamorphic( | 
|  | 618           argc, in_loop, Code::KEYED_CALL_IC); | 
|  | 619       if (!code->IsFailure()) { | 
|  | 620         set_target(Code::cast(code)); | 
|  | 621       } | 
|  | 622     } | 
|  | 623   } | 
|  | 624   Object* result = Runtime::GetObjectProperty(object, key); | 
|  | 625   if (result->IsJSFunction()) return result; | 
|  | 626   result = TryCallAsFunction(result); | 
|  | 627   return result->IsJSFunction() ? | 
|  | 628       result : TypeError("property_not_function", object, key); | 
|  | 629 } | 
|  | 630 | 
|  | 631 | 
| 577 Object* LoadIC::Load(State state, Handle<Object> object, Handle<String> name) { | 632 Object* LoadIC::Load(State state, Handle<Object> object, Handle<String> name) { | 
| 578   // If the object is undefined or null it's illegal to try to get any | 633   // If the object is undefined or null it's illegal to try to get any | 
| 579   // of its properties; throw a TypeError in that case. | 634   // of its properties; throw a TypeError in that case. | 
| 580   if (object->IsUndefined() || object->IsNull()) { | 635   if (object->IsUndefined() || object->IsNull()) { | 
| 581     return TypeError("non_object_property_load", object, name); | 636     return TypeError("non_object_property_load", object, name); | 
| 582   } | 637   } | 
| 583 | 638 | 
| 584   if (FLAG_use_ic) { | 639   if (FLAG_use_ic) { | 
| 585     // Use specialized code for getting the length of strings and | 640     // Use specialized code for getting the length of strings and | 
| 586     // string wrapper objects.  The length property of string wrapper | 641     // string wrapper objects.  The length property of string wrapper | 
| (...skipping 699 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1286 #ifdef DEBUG | 1341 #ifdef DEBUG | 
| 1287   TraceIC("KeyedStoreIC", name, state, target()); | 1342   TraceIC("KeyedStoreIC", name, state, target()); | 
| 1288 #endif | 1343 #endif | 
| 1289 } | 1344 } | 
| 1290 | 1345 | 
| 1291 | 1346 | 
| 1292 // ---------------------------------------------------------------------------- | 1347 // ---------------------------------------------------------------------------- | 
| 1293 // Static IC stub generators. | 1348 // Static IC stub generators. | 
| 1294 // | 1349 // | 
| 1295 | 1350 | 
| 1296 // Used from ic_<arch>.cc. | 1351 static Object* CompileFunction(Object* result, | 
|  | 1352                                Handle<Object> object, | 
|  | 1353                                InLoopFlag in_loop) { | 
|  | 1354   // Compile now with optimization. | 
|  | 1355   HandleScope scope; | 
|  | 1356   Handle<JSFunction> function = Handle<JSFunction>(JSFunction::cast(result)); | 
|  | 1357   if (in_loop == IN_LOOP) { | 
|  | 1358     CompileLazyInLoop(function, object, CLEAR_EXCEPTION); | 
|  | 1359   } else { | 
|  | 1360     CompileLazy(function, object, CLEAR_EXCEPTION); | 
|  | 1361   } | 
|  | 1362   return *function; | 
|  | 1363 } | 
|  | 1364 | 
|  | 1365 | 
|  | 1366 // Used from ic-<arch>.cc. | 
| 1297 Object* CallIC_Miss(Arguments args) { | 1367 Object* CallIC_Miss(Arguments args) { | 
| 1298   NoHandleAllocation na; | 1368   NoHandleAllocation na; | 
| 1299   ASSERT(args.length() == 2); | 1369   ASSERT(args.length() == 2); | 
| 1300   CallIC ic; | 1370   CallIC ic; | 
| 1301   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1371   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 
| 1302   Object* result = | 1372   Object* result = | 
| 1303       ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1)); | 1373       ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1)); | 
| 1304 | 1374 | 
| 1305   // The first time the inline cache is updated may be the first time the | 1375   // The first time the inline cache is updated may be the first time the | 
| 1306   // function it references gets called.  If the function was lazily compiled | 1376   // function it references gets called.  If the function was lazily compiled | 
| 1307   // then the first call will trigger a compilation.  We check for this case | 1377   // then the first call will trigger a compilation.  We check for this case | 
| 1308   // and we do the compilation immediately, instead of waiting for the stub | 1378   // and we do the compilation immediately, instead of waiting for the stub | 
| 1309   // currently attached to the JSFunction object to trigger compilation.  We | 1379   // currently attached to the JSFunction object to trigger compilation.  We | 
| 1310   // do this in the case where we know that the inline cache is inside a loop, | 1380   // do this in the case where we know that the inline cache is inside a loop, | 
| 1311   // because then we know that we want to optimize the function. | 1381   // because then we know that we want to optimize the function. | 
| 1312   if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { | 1382   if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { | 
| 1313     return result; | 1383     return result; | 
| 1314   } | 1384   } | 
| 1315 | 1385   return CompileFunction(result, args.at<Object>(0), ic.target()->ic_in_loop()); | 
| 1316   // Compile now with optimization. |  | 
| 1317   HandleScope scope; |  | 
| 1318   Handle<JSFunction> function = Handle<JSFunction>(JSFunction::cast(result)); |  | 
| 1319   InLoopFlag in_loop = ic.target()->ic_in_loop(); |  | 
| 1320   if (in_loop == IN_LOOP) { |  | 
| 1321     CompileLazyInLoop(function, args.at<Object>(0), CLEAR_EXCEPTION); |  | 
| 1322   } else { |  | 
| 1323     CompileLazy(function, args.at<Object>(0), CLEAR_EXCEPTION); |  | 
| 1324   } |  | 
| 1325   return *function; |  | 
| 1326 } | 1386 } | 
| 1327 | 1387 | 
| 1328 | 1388 | 
| 1329 // Used from ic_<arch>.cc. | 1389 // Used from ic-<arch>.cc. | 
|  | 1390 Object* KeyedCallIC_Miss(Arguments args) { | 
|  | 1391   NoHandleAllocation na; | 
|  | 1392   ASSERT(args.length() == 2); | 
|  | 1393   KeyedCallIC ic; | 
|  | 1394   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 
|  | 1395   Object* result = | 
|  | 1396       ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1)); | 
|  | 1397 | 
|  | 1398   if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { | 
|  | 1399     return result; | 
|  | 1400   } | 
|  | 1401   return CompileFunction(result, args.at<Object>(0), ic.target()->ic_in_loop()); | 
|  | 1402 } | 
|  | 1403 | 
|  | 1404 | 
|  | 1405 // Used from ic-<arch>.cc. | 
| 1330 Object* LoadIC_Miss(Arguments args) { | 1406 Object* LoadIC_Miss(Arguments args) { | 
| 1331   NoHandleAllocation na; | 1407   NoHandleAllocation na; | 
| 1332   ASSERT(args.length() == 2); | 1408   ASSERT(args.length() == 2); | 
| 1333   LoadIC ic; | 1409   LoadIC ic; | 
| 1334   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1410   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 
| 1335   return ic.Load(state, args.at<Object>(0), args.at<String>(1)); | 1411   return ic.Load(state, args.at<Object>(0), args.at<String>(1)); | 
| 1336 } | 1412 } | 
| 1337 | 1413 | 
| 1338 | 1414 | 
| 1339 // Used from ic_<arch>.cc | 1415 // Used from ic-<arch>.cc | 
| 1340 Object* KeyedLoadIC_Miss(Arguments args) { | 1416 Object* KeyedLoadIC_Miss(Arguments args) { | 
| 1341   NoHandleAllocation na; | 1417   NoHandleAllocation na; | 
| 1342   ASSERT(args.length() == 2); | 1418   ASSERT(args.length() == 2); | 
| 1343   KeyedLoadIC ic; | 1419   KeyedLoadIC ic; | 
| 1344   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1420   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 
| 1345   return ic.Load(state, args.at<Object>(0), args.at<Object>(1)); | 1421   return ic.Load(state, args.at<Object>(0), args.at<Object>(1)); | 
| 1346 } | 1422 } | 
| 1347 | 1423 | 
| 1348 | 1424 | 
| 1349 // Used from ic_<arch>.cc. | 1425 // Used from ic-<arch>.cc. | 
| 1350 Object* StoreIC_Miss(Arguments args) { | 1426 Object* StoreIC_Miss(Arguments args) { | 
| 1351   NoHandleAllocation na; | 1427   NoHandleAllocation na; | 
| 1352   ASSERT(args.length() == 3); | 1428   ASSERT(args.length() == 3); | 
| 1353   StoreIC ic; | 1429   StoreIC ic; | 
| 1354   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1430   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 
| 1355   return ic.Store(state, args.at<Object>(0), args.at<String>(1), | 1431   return ic.Store(state, args.at<Object>(0), args.at<String>(1), | 
| 1356                   args.at<Object>(2)); | 1432                   args.at<Object>(2)); | 
| 1357 } | 1433 } | 
| 1358 | 1434 | 
| 1359 | 1435 | 
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1397 | 1473 | 
| 1398   // Set the new property value and do the map transition. | 1474   // Set the new property value and do the map transition. | 
| 1399   object->set_properties(new_storage); | 1475   object->set_properties(new_storage); | 
| 1400   object->set_map(transition); | 1476   object->set_map(transition); | 
| 1401 | 1477 | 
| 1402   // Return the stored value. | 1478   // Return the stored value. | 
| 1403   return value; | 1479   return value; | 
| 1404 } | 1480 } | 
| 1405 | 1481 | 
| 1406 | 1482 | 
| 1407 // Used from ic_<arch>.cc. | 1483 // Used from ic-<arch>.cc. | 
| 1408 Object* KeyedStoreIC_Miss(Arguments args) { | 1484 Object* KeyedStoreIC_Miss(Arguments args) { | 
| 1409   NoHandleAllocation na; | 1485   NoHandleAllocation na; | 
| 1410   ASSERT(args.length() == 3); | 1486   ASSERT(args.length() == 3); | 
| 1411   KeyedStoreIC ic; | 1487   KeyedStoreIC ic; | 
| 1412   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1488   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 
| 1413   return ic.Store(state, args.at<Object>(0), args.at<Object>(1), | 1489   return ic.Store(state, args.at<Object>(0), args.at<Object>(1), | 
| 1414                   args.at<Object>(2)); | 1490                   args.at<Object>(2)); | 
| 1415 } | 1491 } | 
| 1416 | 1492 | 
| 1417 | 1493 | 
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1510 #undef ADDR | 1586 #undef ADDR | 
| 1511 }; | 1587 }; | 
| 1512 | 1588 | 
| 1513 | 1589 | 
| 1514 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 1590 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 
| 1515   return IC_utilities[id]; | 1591   return IC_utilities[id]; | 
| 1516 } | 1592 } | 
| 1517 | 1593 | 
| 1518 | 1594 | 
| 1519 } }  // namespace v8::internal | 1595 } }  // namespace v8::internal | 
| OLD | NEW | 
|---|