Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: src/ic.cc

Issue 2280007: Extend CallIC to support non-constant names.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ic.h ('k') | src/log.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/log.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698