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

Side by Side Diff: src/ic.cc

Issue 6697023: Merge 6800:7180 from the bleeding edge branch to the experimental/gc branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 years, 9 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/ic-inl.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 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 261
262 262
263 void IC::Clear(Address address) { 263 void IC::Clear(Address address) {
264 Code* target = GetTargetAtAddress(address); 264 Code* target = GetTargetAtAddress(address);
265 265
266 // Don't clear debug break inline cache as it will remove the break point. 266 // Don't clear debug break inline cache as it will remove the break point.
267 if (target->ic_state() == DEBUG_BREAK) return; 267 if (target->ic_state() == DEBUG_BREAK) return;
268 268
269 switch (target->kind()) { 269 switch (target->kind()) {
270 case Code::LOAD_IC: return LoadIC::Clear(address, target); 270 case Code::LOAD_IC: return LoadIC::Clear(address, target);
271 case Code::KEYED_LOAD_IC: return KeyedLoadIC::Clear(address, target); 271 case Code::KEYED_LOAD_IC:
272 case Code::KEYED_EXTERNAL_ARRAY_LOAD_IC:
273 return KeyedLoadIC::Clear(address, target);
272 case Code::STORE_IC: return StoreIC::Clear(address, target); 274 case Code::STORE_IC: return StoreIC::Clear(address, target);
273 case Code::KEYED_STORE_IC: return KeyedStoreIC::Clear(address, target); 275 case Code::KEYED_STORE_IC:
276 case Code::KEYED_EXTERNAL_ARRAY_STORE_IC:
277 return KeyedStoreIC::Clear(address, target);
274 case Code::CALL_IC: return CallIC::Clear(address, target); 278 case Code::CALL_IC: return CallIC::Clear(address, target);
275 case Code::KEYED_CALL_IC: return KeyedCallIC::Clear(address, target); 279 case Code::KEYED_CALL_IC: return KeyedCallIC::Clear(address, target);
276 case Code::BINARY_OP_IC: 280 case Code::BINARY_OP_IC:
277 case Code::TYPE_RECORDING_BINARY_OP_IC: 281 case Code::TYPE_RECORDING_BINARY_OP_IC:
278 case Code::COMPARE_IC: 282 case Code::COMPARE_IC:
279 // Clearing these is tricky and does not 283 // Clearing these is tricky and does not
280 // make any performance difference. 284 // make any performance difference.
281 return; 285 return;
282 default: UNREACHABLE(); 286 default: UNREACHABLE();
283 } 287 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 // present) to guarantee failure by holding an invalid map (the null 340 // present) to guarantee failure by holding an invalid map (the null
337 // value). The offset can be patched to anything. 341 // value). The offset can be patched to anything.
338 PatchInlinedStore(address, Heap::null_value(), 0); 342 PatchInlinedStore(address, Heap::null_value(), 0);
339 } 343 }
340 344
341 345
342 void StoreIC::Clear(Address address, Code* target) { 346 void StoreIC::Clear(Address address, Code* target) {
343 if (target->ic_state() == UNINITIALIZED) return; 347 if (target->ic_state() == UNINITIALIZED) return;
344 ClearInlinedVersion(address); 348 ClearInlinedVersion(address);
345 SetTargetAtAddress(address, 349 SetTargetAtAddress(address,
346 target->extra_ic_state() == kStoreICStrict 350 (target->extra_ic_state() == kStrictMode)
347 ? initialize_stub_strict() 351 ? initialize_stub_strict()
348 : initialize_stub()); 352 : initialize_stub());
349 } 353 }
350 354
351 355
352 void KeyedStoreIC::ClearInlinedVersion(Address address) { 356 void KeyedStoreIC::ClearInlinedVersion(Address address) {
353 // Insert null as the elements map to check for. This will make 357 // Insert null as the elements map to check for. This will make
354 // sure that the elements fast-case map check fails so that control 358 // sure that the elements fast-case map check fails so that control
355 // flows to the IC instead of the inlined version. 359 // flows to the IC instead of the inlined version.
356 PatchInlinedStore(address, Heap::null_value()); 360 PatchInlinedStore(address, Heap::null_value());
357 } 361 }
358 362
359 363
360 void KeyedStoreIC::RestoreInlinedVersion(Address address) { 364 void KeyedStoreIC::RestoreInlinedVersion(Address address) {
361 // Restore the fast-case elements map check so that the inlined 365 // Restore the fast-case elements map check so that the inlined
362 // version can be used again. 366 // version can be used again.
363 PatchInlinedStore(address, Heap::fixed_array_map()); 367 PatchInlinedStore(address, Heap::fixed_array_map());
364 } 368 }
365 369
366 370
367 void KeyedStoreIC::Clear(Address address, Code* target) { 371 void KeyedStoreIC::Clear(Address address, Code* target) {
368 if (target->ic_state() == UNINITIALIZED) return; 372 if (target->ic_state() == UNINITIALIZED) return;
369 SetTargetAtAddress(address, initialize_stub()); 373 SetTargetAtAddress(address,
374 (target->extra_ic_state() == kStrictMode)
375 ? initialize_stub_strict()
376 : initialize_stub());
370 } 377 }
371 378
372 379
373 static bool HasInterceptorGetter(JSObject* object) { 380 static bool HasInterceptorGetter(JSObject* object) {
374 return !object->GetNamedInterceptor()->getter()->IsUndefined(); 381 return !object->GetNamedInterceptor()->getter()->IsUndefined();
375 } 382 }
376 383
377 384
378 static void LookupForRead(Object* object, 385 static void LookupForRead(Object* object,
379 String* name, 386 String* name,
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 StackFrameLocator locator; 435 StackFrameLocator locator;
429 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); 436 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
430 int index = frame->ComputeExpressionsCount() - (argc + 1); 437 int index = frame->ComputeExpressionsCount() - (argc + 1);
431 frame->SetExpression(index, *target); 438 frame->SetExpression(index, *target);
432 } 439 }
433 440
434 return *delegate; 441 return *delegate;
435 } 442 }
436 443
437 444
438 void CallICBase::ReceiverToObject(Handle<Object> object) { 445 void CallICBase::ReceiverToObjectIfRequired(Handle<Object> callee,
439 HandleScope scope; 446 Handle<Object> object) {
440 Handle<Object> receiver(object); 447 if (callee->IsJSFunction()) {
448 Handle<JSFunction> function = Handle<JSFunction>::cast(callee);
449 if (function->shared()->strict_mode() || function->IsBuiltin()) {
450 // Do not wrap receiver for strict mode functions or for builtins.
451 return;
452 }
453 }
441 454
442 // Change the receiver to the result of calling ToObject on it. 455 // And only wrap string, number or boolean.
443 const int argc = this->target()->arguments_count(); 456 if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
444 StackFrameLocator locator; 457 // Change the receiver to the result of calling ToObject on it.
445 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); 458 const int argc = this->target()->arguments_count();
446 int index = frame->ComputeExpressionsCount() - (argc + 1); 459 StackFrameLocator locator;
447 frame->SetExpression(index, *Factory::ToObject(object)); 460 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
461 int index = frame->ComputeExpressionsCount() - (argc + 1);
462 frame->SetExpression(index, *Factory::ToObject(object));
463 }
448 } 464 }
449 465
450 466
451 MaybeObject* CallICBase::LoadFunction(State state, 467 MaybeObject* CallICBase::LoadFunction(State state,
452 Code::ExtraICState extra_ic_state, 468 Code::ExtraICState extra_ic_state,
453 Handle<Object> object, 469 Handle<Object> object,
454 Handle<String> name) { 470 Handle<String> name) {
455 // If the object is undefined or null it's illegal to try to get any 471 // If the object is undefined or null it's illegal to try to get any
456 // of its properties; throw a TypeError in that case. 472 // of its properties; throw a TypeError in that case.
457 if (object->IsUndefined() || object->IsNull()) { 473 if (object->IsUndefined() || object->IsNull()) {
458 return TypeError("non_object_property_call", object, name); 474 return TypeError("non_object_property_call", object, name);
459 } 475 }
460 476
461 if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
462 ReceiverToObject(object);
463 }
464
465 // Check if the name is trivially convertible to an index and get 477 // Check if the name is trivially convertible to an index and get
466 // the element if so. 478 // the element if so.
467 uint32_t index; 479 uint32_t index;
468 if (name->AsArrayIndex(&index)) { 480 if (name->AsArrayIndex(&index)) {
469 Object* result; 481 Object* result;
470 { MaybeObject* maybe_result = object->GetElement(index); 482 { MaybeObject* maybe_result = object->GetElement(index);
471 if (!maybe_result->ToObject(&result)) return maybe_result; 483 if (!maybe_result->ToObject(&result)) return maybe_result;
472 } 484 }
473 485
474 if (result->IsJSFunction()) return result; 486 if (result->IsJSFunction()) return result;
(...skipping 23 matching lines...) Expand all
498 UpdateCaches(&lookup, state, extra_ic_state, object, name); 510 UpdateCaches(&lookup, state, extra_ic_state, object, name);
499 } 511 }
500 512
501 // Get the property. 513 // Get the property.
502 PropertyAttributes attr; 514 PropertyAttributes attr;
503 Object* result; 515 Object* result;
504 { MaybeObject* maybe_result = 516 { MaybeObject* maybe_result =
505 object->GetProperty(*object, &lookup, *name, &attr); 517 object->GetProperty(*object, &lookup, *name, &attr);
506 if (!maybe_result->ToObject(&result)) return maybe_result; 518 if (!maybe_result->ToObject(&result)) return maybe_result;
507 } 519 }
520
508 if (lookup.type() == INTERCEPTOR) { 521 if (lookup.type() == INTERCEPTOR) {
509 // If the object does not have the requested property, check which 522 // If the object does not have the requested property, check which
510 // exception we need to throw. 523 // exception we need to throw.
511 if (attr == ABSENT) { 524 if (attr == ABSENT) {
512 if (IsContextual(object)) { 525 if (IsContextual(object)) {
513 return ReferenceError("not_defined", name); 526 return ReferenceError("not_defined", name);
514 } 527 }
515 return TypeError("undefined_method", object, name); 528 return TypeError("undefined_method", object, name);
516 } 529 }
517 } 530 }
518 531
519 ASSERT(result != Heap::the_hole_value()); 532 ASSERT(!result->IsTheHole());
520 533
521 if (result->IsJSFunction()) { 534 HandleScope scope;
535 // Wrap result in a handle because ReceiverToObjectIfRequired may allocate
536 // new object and cause GC.
537 Handle<Object> result_handle(result);
538 // 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
540 // called as functions do.
541 ReceiverToObjectIfRequired(result_handle, object);
542
543 if (result_handle->IsJSFunction()) {
522 #ifdef ENABLE_DEBUGGER_SUPPORT 544 #ifdef ENABLE_DEBUGGER_SUPPORT
523 // Handle stepping into a function if step into is active. 545 // Handle stepping into a function if step into is active.
524 if (Debug::StepInActive()) { 546 if (Debug::StepInActive()) {
525 // Protect the result in a handle as the debugger can allocate and might 547 // Protect the result in a handle as the debugger can allocate and might
526 // cause GC. 548 // cause GC.
527 HandleScope scope; 549 Handle<JSFunction> function(JSFunction::cast(*result_handle));
528 Handle<JSFunction> function(JSFunction::cast(result));
529 Debug::HandleStepIn(function, object, fp(), false); 550 Debug::HandleStepIn(function, object, fp(), false);
530 return *function; 551 return *function;
531 } 552 }
532 #endif 553 #endif
533 554
534 return result; 555 return *result_handle;
535 } 556 }
536 557
537 // Try to find a suitable function delegate for the object at hand. 558 // Try to find a suitable function delegate for the object at hand.
538 result = TryCallAsFunction(result); 559 result_handle = Handle<Object>(TryCallAsFunction(*result_handle));
539 MaybeObject* answer = result; 560 if (result_handle->IsJSFunction()) return *result_handle;
540 if (!result->IsJSFunction()) { 561
541 answer = TypeError("property_not_function", object, name); 562 return TypeError("property_not_function", object, name);
542 }
543 return answer;
544 } 563 }
545 564
546 565
547 bool CallICBase::TryUpdateExtraICState(LookupResult* lookup, 566 bool CallICBase::TryUpdateExtraICState(LookupResult* lookup,
548 Handle<Object> object, 567 Handle<Object> object,
549 Code::ExtraICState* extra_ic_state) { 568 Code::ExtraICState* extra_ic_state) {
550 ASSERT(kind_ == Code::CALL_IC); 569 ASSERT(kind_ == Code::CALL_IC);
551 if (lookup->type() != CONSTANT_FUNCTION) return false; 570 if (lookup->type() != CONSTANT_FUNCTION) return false;
552 JSFunction* function = lookup->GetConstantFunction(); 571 JSFunction* function = lookup->GetConstantFunction();
553 if (!function->shared()->HasBuiltinFunctionId()) return false; 572 if (!function->shared()->HasBuiltinFunctionId()) return false;
554 573
555 // Fetch the arguments passed to the called function. 574 // Fetch the arguments passed to the called function.
556 const int argc = target()->arguments_count(); 575 const int argc = target()->arguments_count();
557 Address entry = Top::c_entry_fp(Top::GetCurrentThread()); 576 Address entry = Top::c_entry_fp(Top::GetCurrentThread());
558 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); 577 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
559 Arguments args(argc + 1, 578 Arguments args(argc + 1,
560 &Memory::Object_at(fp + 579 &Memory::Object_at(fp +
561 StandardFrameConstants::kCallerSPOffset + 580 StandardFrameConstants::kCallerSPOffset +
562 argc * kPointerSize)); 581 argc * kPointerSize));
563 switch (function->shared()->builtin_function_id()) { 582 switch (function->shared()->builtin_function_id()) {
564 case kStringCharCodeAt: 583 case kStringCharCodeAt:
565 case kStringCharAt: 584 case kStringCharAt:
566 if (object->IsString()) { 585 if (object->IsString()) {
567 String* string = String::cast(*object); 586 String* string = String::cast(*object);
568 // Check that there's the right wrapper in the receiver slot. 587 // Check there's the right string value or wrapper in the receiver slot.
569 ASSERT(string == JSValue::cast(args[0])->value()); 588 ASSERT(string == args[0] || string == JSValue::cast(args[0])->value());
570 // If we're in the default (fastest) state and the index is 589 // If we're in the default (fastest) state and the index is
571 // out of bounds, update the state to record this fact. 590 // out of bounds, update the state to record this fact.
572 if (*extra_ic_state == DEFAULT_STRING_STUB && 591 if (*extra_ic_state == DEFAULT_STRING_STUB &&
573 argc >= 1 && args[1]->IsNumber()) { 592 argc >= 1 && args[1]->IsNumber()) {
574 double index; 593 double index;
575 if (args[1]->IsSmi()) { 594 if (args[1]->IsSmi()) {
576 index = Smi::cast(args[1])->value(); 595 index = Smi::cast(args[1])->value();
577 } else { 596 } else {
578 ASSERT(args[1]->IsHeapNumber()); 597 ASSERT(args[1]->IsHeapNumber());
579 index = DoubleToInteger(HeapNumber::cast(args[1])->value()); 598 index = DoubleToInteger(HeapNumber::cast(args[1])->value());
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
768 return CallICBase::LoadFunction(state, 787 return CallICBase::LoadFunction(state,
769 Code::kNoExtraICState, 788 Code::kNoExtraICState,
770 object, 789 object,
771 Handle<String>::cast(key)); 790 Handle<String>::cast(key));
772 } 791 }
773 792
774 if (object->IsUndefined() || object->IsNull()) { 793 if (object->IsUndefined() || object->IsNull()) {
775 return TypeError("non_object_property_call", object, key); 794 return TypeError("non_object_property_call", object, key);
776 } 795 }
777 796
778 if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
779 ReceiverToObject(object);
780 }
781
782 if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) { 797 if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) {
783 int argc = target()->arguments_count(); 798 int argc = target()->arguments_count();
784 InLoopFlag in_loop = target()->ic_in_loop(); 799 InLoopFlag in_loop = target()->ic_in_loop();
785 MaybeObject* maybe_code = StubCache::ComputeCallMegamorphic( 800 MaybeObject* maybe_code = StubCache::ComputeCallMegamorphic(
786 argc, in_loop, Code::KEYED_CALL_IC); 801 argc, in_loop, Code::KEYED_CALL_IC);
787 Object* code; 802 Object* code;
788 if (maybe_code->ToObject(&code)) { 803 if (maybe_code->ToObject(&code)) {
789 set_target(Code::cast(code)); 804 set_target(Code::cast(code));
790 #ifdef DEBUG 805 #ifdef DEBUG
791 TraceIC( 806 TraceIC(
792 "KeyedCallIC", key, state, target(), in_loop ? " (in-loop)" : ""); 807 "KeyedCallIC", key, state, target(), in_loop ? " (in-loop)" : "");
793 #endif 808 #endif
794 } 809 }
795 } 810 }
796 Object* result; 811
797 { MaybeObject* maybe_result = Runtime::GetObjectProperty(object, key); 812 HandleScope scope;
798 if (!maybe_result->ToObject(&result)) return maybe_result; 813 Handle<Object> result = GetProperty(object, key);
799 } 814 RETURN_IF_EMPTY_HANDLE(result);
800 if (result->IsJSFunction()) return result; 815
801 result = TryCallAsFunction(result); 816 // Make receiver an object if the callee requires it. Strict mode or builtin
802 MaybeObject* answer = result; 817 // functions do not wrap the receiver, non-strict functions and objects
803 if (!result->IsJSFunction()) { 818 // called as functions do.
804 answer = TypeError("property_not_function", object, key); 819 ReceiverToObjectIfRequired(result, object);
805 } 820
806 return answer; 821 if (result->IsJSFunction()) return *result;
822 result = Handle<Object>(TryCallAsFunction(*result));
823 if (result->IsJSFunction()) return *result;
824
825 return TypeError("property_not_function", object, key);
807 } 826 }
808 827
809 828
810 #ifdef DEBUG 829 #ifdef DEBUG
811 #define TRACE_IC_NAMED(msg, name) \ 830 #define TRACE_IC_NAMED(msg, name) \
812 if (FLAG_trace_ic) PrintF(msg, *(name)->ToCString()) 831 if (FLAG_trace_ic) PrintF(msg, *(name)->ToCString())
813 #else 832 #else
814 #define TRACE_IC_NAMED(msg, name) 833 #define TRACE_IC_NAMED(msg, name)
815 #endif 834 #endif
816 835
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
1208 if (use_ic) { 1227 if (use_ic) {
1209 Code* stub = generic_stub(); 1228 Code* stub = generic_stub();
1210 if (state == UNINITIALIZED) { 1229 if (state == UNINITIALIZED) {
1211 if (object->IsString() && key->IsNumber()) { 1230 if (object->IsString() && key->IsNumber()) {
1212 stub = string_stub(); 1231 stub = string_stub();
1213 } else if (object->IsJSObject()) { 1232 } else if (object->IsJSObject()) {
1214 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1233 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1215 if (receiver->HasExternalArrayElements()) { 1234 if (receiver->HasExternalArrayElements()) {
1216 MaybeObject* probe = 1235 MaybeObject* probe =
1217 StubCache::ComputeKeyedLoadOrStoreExternalArray(*receiver, 1236 StubCache::ComputeKeyedLoadOrStoreExternalArray(*receiver,
1218 false); 1237 false,
1238 kNonStrictMode);
1219 stub = probe->IsFailure() ? 1239 stub = probe->IsFailure() ?
1220 NULL : Code::cast(probe->ToObjectUnchecked()); 1240 NULL : Code::cast(probe->ToObjectUnchecked());
1221 } else if (receiver->HasIndexedInterceptor()) { 1241 } else if (receiver->HasIndexedInterceptor()) {
1222 stub = indexed_interceptor_stub(); 1242 stub = indexed_interceptor_stub();
1223 } else if (receiver->HasPixelElements()) {
1224 MaybeObject* probe =
1225 StubCache::ComputeKeyedLoadPixelArray(*receiver);
1226 stub = probe->IsFailure() ?
1227 NULL : Code::cast(probe->ToObjectUnchecked());
1228 } else if (key->IsSmi() && 1243 } else if (key->IsSmi() &&
1229 receiver->map()->has_fast_elements()) { 1244 receiver->map()->has_fast_elements()) {
1230 MaybeObject* probe = 1245 MaybeObject* probe =
1231 StubCache::ComputeKeyedLoadSpecialized(*receiver); 1246 StubCache::ComputeKeyedLoadSpecialized(*receiver);
1232 stub = probe->IsFailure() ? 1247 stub = probe->IsFailure() ?
1233 NULL : Code::cast(probe->ToObjectUnchecked()); 1248 NULL : Code::cast(probe->ToObjectUnchecked());
1234 } 1249 }
1235 } 1250 }
1236 } 1251 }
1237 if (stub != NULL) set_target(stub); 1252 if (stub != NULL) set_target(stub);
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
1364 object->LocalLookupRealNamedProperty(name, lookup); 1379 object->LocalLookupRealNamedProperty(name, lookup);
1365 return StoreICableLookup(lookup); 1380 return StoreICableLookup(lookup);
1366 } 1381 }
1367 } 1382 }
1368 1383
1369 return true; 1384 return true;
1370 } 1385 }
1371 1386
1372 1387
1373 MaybeObject* StoreIC::Store(State state, 1388 MaybeObject* StoreIC::Store(State state,
1374 Code::ExtraICState extra_ic_state, 1389 StrictModeFlag strict_mode,
1375 Handle<Object> object, 1390 Handle<Object> object,
1376 Handle<String> name, 1391 Handle<String> name,
1377 Handle<Object> value) { 1392 Handle<Object> value) {
1378 // If the object is undefined or null it's illegal to try to set any 1393 // If the object is undefined or null it's illegal to try to set any
1379 // properties on it; throw a TypeError in that case. 1394 // properties on it; throw a TypeError in that case.
1380 if (object->IsUndefined() || object->IsNull()) { 1395 if (object->IsUndefined() || object->IsNull()) {
1381 return TypeError("non_object_property_store", object, name); 1396 return TypeError("non_object_property_store", object, name);
1382 } 1397 }
1383 1398
1384 // Ignore stores where the receiver is not a JSObject. 1399 if (!object->IsJSObject()) {
1385 if (!object->IsJSObject()) return *value; 1400 // The length property of string values is read-only. Throw in strict mode.
1401 if (strict_mode == kStrictMode && object->IsString() &&
1402 name->Equals(Heap::length_symbol())) {
1403 return TypeError("strict_read_only_property", object, name);
1404 }
1405 // Ignore stores where the receiver is not a JSObject.
1406 return *value;
1407 }
1408
1386 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1409 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1387 1410
1388 // Check if the given name is an array index. 1411 // Check if the given name is an array index.
1389 uint32_t index; 1412 uint32_t index;
1390 if (name->AsArrayIndex(&index)) { 1413 if (name->AsArrayIndex(&index)) {
1391 HandleScope scope; 1414 HandleScope scope;
1392 Handle<Object> result = SetElement(receiver, index, value); 1415 Handle<Object> result = SetElement(receiver, index, value, strict_mode);
1393 if (result.is_null()) return Failure::Exception(); 1416 if (result.is_null()) return Failure::Exception();
1394 return *value; 1417 return *value;
1395 } 1418 }
1396 1419
1397 // Use specialized code for setting the length of arrays. 1420 // Use specialized code for setting the length of arrays.
1398 if (receiver->IsJSArray() 1421 if (receiver->IsJSArray()
1399 && name->Equals(Heap::length_symbol()) 1422 && name->Equals(Heap::length_symbol())
1400 && receiver->AllowsSetElementsLength()) { 1423 && receiver->AllowsSetElementsLength()) {
1401 #ifdef DEBUG 1424 #ifdef DEBUG
1402 if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n"); 1425 if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n");
1403 #endif 1426 #endif
1404 Builtins::Name target = (extra_ic_state == kStoreICStrict) 1427 Builtins::Name target = (strict_mode == kStrictMode)
1405 ? Builtins::StoreIC_ArrayLength_Strict 1428 ? Builtins::StoreIC_ArrayLength_Strict
1406 : Builtins::StoreIC_ArrayLength; 1429 : Builtins::StoreIC_ArrayLength;
1407 set_target(Builtins::builtin(target)); 1430 set_target(Builtins::builtin(target));
1408 return receiver->SetProperty(*name, *value, NONE); 1431 return receiver->SetProperty(*name, *value, NONE, strict_mode);
1409 } 1432 }
1410 1433
1411 // Lookup the property locally in the receiver. 1434 // Lookup the property locally in the receiver.
1412 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) { 1435 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) {
1413 LookupResult lookup; 1436 LookupResult lookup;
1414 1437
1415 if (LookupForWrite(*receiver, *name, &lookup)) { 1438 if (LookupForWrite(*receiver, *name, &lookup)) {
1416 bool can_be_inlined = 1439 bool can_be_inlined =
1417 state == UNINITIALIZED && 1440 state == UNINITIALIZED &&
1418 lookup.IsProperty() && 1441 lookup.IsProperty() &&
1419 lookup.holder() == *receiver && 1442 lookup.holder() == *receiver &&
1420 lookup.type() == FIELD && 1443 lookup.type() == FIELD &&
1421 !receiver->IsAccessCheckNeeded(); 1444 !receiver->IsAccessCheckNeeded();
1422 1445
1423 if (can_be_inlined) { 1446 if (can_be_inlined) {
1424 Map* map = lookup.holder()->map(); 1447 Map* map = lookup.holder()->map();
1425 // Property's index in the properties array. If negative we have 1448 // Property's index in the properties array. If negative we have
1426 // an inobject property. 1449 // an inobject property.
1427 int index = lookup.GetFieldIndex() - map->inobject_properties(); 1450 int index = lookup.GetFieldIndex() - map->inobject_properties();
1428 if (index < 0) { 1451 if (index < 0) {
1429 // Index is an offset from the end of the object. 1452 // Index is an offset from the end of the object.
1430 int offset = map->instance_size() + (index * kPointerSize); 1453 int offset = map->instance_size() + (index * kPointerSize);
1431 if (PatchInlinedStore(address(), map, offset)) { 1454 if (PatchInlinedStore(address(), map, offset)) {
1432 set_target(megamorphic_stub()); 1455 set_target((strict_mode == kStrictMode)
1456 ? megamorphic_stub_strict()
1457 : megamorphic_stub());
1433 #ifdef DEBUG 1458 #ifdef DEBUG
1434 if (FLAG_trace_ic) { 1459 if (FLAG_trace_ic) {
1435 PrintF("[StoreIC : inline patch %s]\n", *name->ToCString()); 1460 PrintF("[StoreIC : inline patch %s]\n", *name->ToCString());
1436 } 1461 }
1437 #endif 1462 #endif
1438 return receiver->SetProperty(*name, *value, NONE); 1463 return receiver->SetProperty(*name, *value, NONE, strict_mode);
1439 #ifdef DEBUG 1464 #ifdef DEBUG
1440 1465
1441 } else { 1466 } else {
1442 if (FLAG_trace_ic) { 1467 if (FLAG_trace_ic) {
1443 PrintF("[StoreIC : no inline patch %s (patching failed)]\n", 1468 PrintF("[StoreIC : no inline patch %s (patching failed)]\n",
1444 *name->ToCString()); 1469 *name->ToCString());
1445 } 1470 }
1446 } 1471 }
1447 } else { 1472 } else {
1448 if (FLAG_trace_ic) { 1473 if (FLAG_trace_ic) {
1449 PrintF("[StoreIC : no inline patch %s (not inobject)]\n", 1474 PrintF("[StoreIC : no inline patch %s (not inobject)]\n",
1450 *name->ToCString()); 1475 *name->ToCString());
1451 } 1476 }
1452 } 1477 }
1453 } else { 1478 } else {
1454 if (state == PREMONOMORPHIC) { 1479 if (state == PREMONOMORPHIC) {
1455 if (FLAG_trace_ic) { 1480 if (FLAG_trace_ic) {
1456 PrintF("[StoreIC : no inline patch %s (not inlinable)]\n", 1481 PrintF("[StoreIC : no inline patch %s (not inlinable)]\n",
1457 *name->ToCString()); 1482 *name->ToCString());
1458 #endif 1483 #endif
1459 } 1484 }
1460 } 1485 }
1461 } 1486 }
1462 1487
1463 // If no inlined store ic was patched, generate a stub for this 1488 // If no inlined store ic was patched, generate a stub for this
1464 // store. 1489 // store.
1465 UpdateCaches(&lookup, state, extra_ic_state, receiver, name, value); 1490 UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
1466 } else { 1491 } else {
1467 // Strict mode doesn't allow setting non-existent global property. 1492 // Strict mode doesn't allow setting non-existent global property
1468 if (extra_ic_state == kStoreICStrict && IsContextual(object)) { 1493 // or an assignment to a read only property.
1469 return ReferenceError("not_defined", name); 1494 if (strict_mode == kStrictMode) {
1495 if (lookup.IsFound() && lookup.IsReadOnly()) {
1496 return TypeError("strict_read_only_property", object, name);
1497 } else if (IsContextual(object)) {
1498 return ReferenceError("not_defined", name);
1499 }
1470 } 1500 }
1471 } 1501 }
1472 } 1502 }
1473 1503
1474 if (receiver->IsJSGlobalProxy()) { 1504 if (receiver->IsJSGlobalProxy()) {
1475 // Generate a generic stub that goes to the runtime when we see a global 1505 // Generate a generic stub that goes to the runtime when we see a global
1476 // proxy as receiver. 1506 // proxy as receiver.
1477 Code* stub = (extra_ic_state == kStoreICStrict) 1507 Code* stub = (strict_mode == kStrictMode)
1478 ? global_proxy_stub_strict() 1508 ? global_proxy_stub_strict()
1479 : global_proxy_stub(); 1509 : global_proxy_stub();
1480 if (target() != stub) { 1510 if (target() != stub) {
1481 set_target(stub); 1511 set_target(stub);
1482 #ifdef DEBUG 1512 #ifdef DEBUG
1483 TraceIC("StoreIC", name, state, target()); 1513 TraceIC("StoreIC", name, state, target());
1484 #endif 1514 #endif
1485 } 1515 }
1486 } 1516 }
1487 1517
1488 // Set the property. 1518 // Set the property.
1489 return receiver->SetProperty(*name, *value, NONE); 1519 return receiver->SetProperty(*name, *value, NONE, strict_mode);
1490 } 1520 }
1491 1521
1492 1522
1493 void StoreIC::UpdateCaches(LookupResult* lookup, 1523 void StoreIC::UpdateCaches(LookupResult* lookup,
1494 State state, 1524 State state,
1495 Code::ExtraICState extra_ic_state, 1525 StrictModeFlag strict_mode,
1496 Handle<JSObject> receiver, 1526 Handle<JSObject> receiver,
1497 Handle<String> name, 1527 Handle<String> name,
1498 Handle<Object> value) { 1528 Handle<Object> value) {
1499 // Skip JSGlobalProxy. 1529 // Skip JSGlobalProxy.
1500 ASSERT(!receiver->IsJSGlobalProxy()); 1530 ASSERT(!receiver->IsJSGlobalProxy());
1501 1531
1502 ASSERT(StoreICableLookup(lookup)); 1532 ASSERT(StoreICableLookup(lookup));
1503 1533
1504 // If the property has a non-field type allowing map transitions 1534 // If the property has a non-field type allowing map transitions
1505 // where there is extra room in the object, we leave the IC in its 1535 // where there is extra room in the object, we leave the IC in its
1506 // current state. 1536 // current state.
1507 PropertyType type = lookup->type(); 1537 PropertyType type = lookup->type();
1508 1538
1509 // Compute the code stub for this store; used for rewriting to 1539 // Compute the code stub for this store; used for rewriting to
1510 // monomorphic state and making sure that the code stub is in the 1540 // monomorphic state and making sure that the code stub is in the
1511 // stub cache. 1541 // stub cache.
1512 MaybeObject* maybe_code = NULL; 1542 MaybeObject* maybe_code = NULL;
1513 Object* code = NULL; 1543 Object* code = NULL;
1514 switch (type) { 1544 switch (type) {
1515 case FIELD: { 1545 case FIELD: {
1516 maybe_code = StubCache::ComputeStoreField( 1546 maybe_code = StubCache::ComputeStoreField(
1517 *name, *receiver, lookup->GetFieldIndex(), NULL, extra_ic_state); 1547 *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode);
1518 break; 1548 break;
1519 } 1549 }
1520 case MAP_TRANSITION: { 1550 case MAP_TRANSITION: {
1521 if (lookup->GetAttributes() != NONE) return; 1551 if (lookup->GetAttributes() != NONE) return;
1522 HandleScope scope; 1552 HandleScope scope;
1523 ASSERT(type == MAP_TRANSITION); 1553 ASSERT(type == MAP_TRANSITION);
1524 Handle<Map> transition(lookup->GetTransitionMap()); 1554 Handle<Map> transition(lookup->GetTransitionMap());
1525 int index = transition->PropertyIndexFor(*name); 1555 int index = transition->PropertyIndexFor(*name);
1526 maybe_code = StubCache::ComputeStoreField( 1556 maybe_code = StubCache::ComputeStoreField(
1527 *name, *receiver, index, *transition, extra_ic_state); 1557 *name, *receiver, index, *transition, strict_mode);
1528 break; 1558 break;
1529 } 1559 }
1530 case NORMAL: { 1560 case NORMAL: {
1531 if (receiver->IsGlobalObject()) { 1561 if (receiver->IsGlobalObject()) {
1532 // The stub generated for the global object picks the value directly 1562 // The stub generated for the global object picks the value directly
1533 // from the property cell. So the property must be directly on the 1563 // from the property cell. So the property must be directly on the
1534 // global object. 1564 // global object.
1535 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); 1565 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
1536 JSGlobalPropertyCell* cell = 1566 JSGlobalPropertyCell* cell =
1537 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); 1567 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
1538 maybe_code = StubCache::ComputeStoreGlobal( 1568 maybe_code = StubCache::ComputeStoreGlobal(
1539 *name, *global, cell, extra_ic_state); 1569 *name, *global, cell, strict_mode);
1540 } else { 1570 } else {
1541 if (lookup->holder() != *receiver) return; 1571 if (lookup->holder() != *receiver) return;
1542 maybe_code = StubCache::ComputeStoreNormal(extra_ic_state); 1572 maybe_code = StubCache::ComputeStoreNormal(strict_mode);
1543 } 1573 }
1544 break; 1574 break;
1545 } 1575 }
1546 case CALLBACKS: { 1576 case CALLBACKS: {
1547 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; 1577 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
1548 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); 1578 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
1549 if (v8::ToCData<Address>(callback->setter()) == 0) return; 1579 if (v8::ToCData<Address>(callback->setter()) == 0) return;
1550 maybe_code = StubCache::ComputeStoreCallback( 1580 maybe_code = StubCache::ComputeStoreCallback(
1551 *name, *receiver, callback, extra_ic_state); 1581 *name, *receiver, callback, strict_mode);
1552 break; 1582 break;
1553 } 1583 }
1554 case INTERCEPTOR: { 1584 case INTERCEPTOR: {
1555 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined()); 1585 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined());
1556 maybe_code = StubCache::ComputeStoreInterceptor( 1586 maybe_code = StubCache::ComputeStoreInterceptor(
1557 *name, *receiver, extra_ic_state); 1587 *name, *receiver, strict_mode);
1558 break; 1588 break;
1559 } 1589 }
1560 default: 1590 default:
1561 return; 1591 return;
1562 } 1592 }
1563 1593
1564 // If we're unable to compute the stub (not enough memory left), we 1594 // If we're unable to compute the stub (not enough memory left), we
1565 // simply avoid updating the caches. 1595 // simply avoid updating the caches.
1566 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return; 1596 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
1567 1597
1568 // Patch the call site depending on the state of the cache. 1598 // Patch the call site depending on the state of the cache.
1569 if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) { 1599 if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) {
1570 set_target(Code::cast(code)); 1600 set_target(Code::cast(code));
1571 } else if (state == MONOMORPHIC) { 1601 } else if (state == MONOMORPHIC) {
1572 // Only move to megamorphic if the target changes. 1602 // Only move to megamorphic if the target changes.
1573 if (target() != Code::cast(code)) { 1603 if (target() != Code::cast(code)) {
1574 set_target(extra_ic_state == kStoreICStrict 1604 set_target((strict_mode == kStrictMode)
1575 ? megamorphic_stub_strict() 1605 ? megamorphic_stub_strict()
1576 : megamorphic_stub()); 1606 : megamorphic_stub());
1577 } 1607 }
1578 } else if (state == MEGAMORPHIC) { 1608 } else if (state == MEGAMORPHIC) {
1579 // Update the stub cache. 1609 // Update the stub cache.
1580 StubCache::Set(*name, receiver->map(), Code::cast(code)); 1610 StubCache::Set(*name, receiver->map(), Code::cast(code));
1581 } 1611 }
1582 1612
1583 #ifdef DEBUG 1613 #ifdef DEBUG
1584 TraceIC("StoreIC", name, state, target()); 1614 TraceIC("StoreIC", name, state, target());
1585 #endif 1615 #endif
1586 } 1616 }
1587 1617
1588 1618
1589 MaybeObject* KeyedStoreIC::Store(State state, 1619 MaybeObject* KeyedStoreIC::Store(State state,
1620 StrictModeFlag strict_mode,
1590 Handle<Object> object, 1621 Handle<Object> object,
1591 Handle<Object> key, 1622 Handle<Object> key,
1592 Handle<Object> value) { 1623 Handle<Object> value) {
1593 if (key->IsSymbol()) { 1624 if (key->IsSymbol()) {
1594 Handle<String> name = Handle<String>::cast(key); 1625 Handle<String> name = Handle<String>::cast(key);
1595 1626
1596 // If the object is undefined or null it's illegal to try to set any 1627 // If the object is undefined or null it's illegal to try to set any
1597 // properties on it; throw a TypeError in that case. 1628 // properties on it; throw a TypeError in that case.
1598 if (object->IsUndefined() || object->IsNull()) { 1629 if (object->IsUndefined() || object->IsNull()) {
1599 return TypeError("non_object_property_store", object, name); 1630 return TypeError("non_object_property_store", object, name);
1600 } 1631 }
1601 1632
1602 // Ignore stores where the receiver is not a JSObject. 1633 // Ignore stores where the receiver is not a JSObject.
1603 if (!object->IsJSObject()) return *value; 1634 if (!object->IsJSObject()) return *value;
1604 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1635 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1605 1636
1606 // Check if the given name is an array index. 1637 // Check if the given name is an array index.
1607 uint32_t index; 1638 uint32_t index;
1608 if (name->AsArrayIndex(&index)) { 1639 if (name->AsArrayIndex(&index)) {
1609 HandleScope scope; 1640 HandleScope scope;
1610 Handle<Object> result = SetElement(receiver, index, value); 1641 Handle<Object> result = SetElement(receiver, index, value, strict_mode);
1611 if (result.is_null()) return Failure::Exception(); 1642 if (result.is_null()) return Failure::Exception();
1612 return *value; 1643 return *value;
1613 } 1644 }
1614 1645
1615 // Lookup the property locally in the receiver. 1646 // Lookup the property locally in the receiver.
1616 LookupResult lookup; 1647 LookupResult lookup;
1617 receiver->LocalLookup(*name, &lookup); 1648 receiver->LocalLookup(*name, &lookup);
1618 1649
1619 // Update inline cache and stub cache. 1650 // Update inline cache and stub cache.
1620 if (FLAG_use_ic) { 1651 if (FLAG_use_ic) {
1621 UpdateCaches(&lookup, state, receiver, name, value); 1652 UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
1622 } 1653 }
1623 1654
1624 // Set the property. 1655 // Set the property.
1625 return receiver->SetProperty(*name, *value, NONE); 1656 return receiver->SetProperty(*name, *value, NONE, strict_mode);
1626 } 1657 }
1627 1658
1628 // Do not use ICs for objects that require access checks (including 1659 // Do not use ICs for objects that require access checks (including
1629 // the global object). 1660 // the global object).
1630 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); 1661 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
1631 ASSERT(!(use_ic && object->IsJSGlobalProxy())); 1662 ASSERT(!(use_ic && object->IsJSGlobalProxy()));
1632 1663
1633 if (use_ic) { 1664 if (use_ic) {
1634 Code* stub = generic_stub(); 1665 Code* stub =
1666 (strict_mode == kStrictMode) ? generic_stub_strict() : generic_stub();
1635 if (state == UNINITIALIZED) { 1667 if (state == UNINITIALIZED) {
1636 if (object->IsJSObject()) { 1668 if (object->IsJSObject()) {
1637 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1669 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1638 if (receiver->HasExternalArrayElements()) { 1670 if (receiver->HasExternalArrayElements()) {
1639 MaybeObject* probe = 1671 MaybeObject* probe =
1640 StubCache::ComputeKeyedLoadOrStoreExternalArray(*receiver, true); 1672 StubCache::ComputeKeyedLoadOrStoreExternalArray(
1641 stub = probe->IsFailure() ? 1673 *receiver, true, strict_mode);
1642 NULL : Code::cast(probe->ToObjectUnchecked());
1643 } else if (receiver->HasPixelElements()) {
1644 MaybeObject* probe =
1645 StubCache::ComputeKeyedStorePixelArray(*receiver);
1646 stub = probe->IsFailure() ? 1674 stub = probe->IsFailure() ?
1647 NULL : Code::cast(probe->ToObjectUnchecked()); 1675 NULL : Code::cast(probe->ToObjectUnchecked());
1648 } else if (key->IsSmi() && receiver->map()->has_fast_elements()) { 1676 } else if (key->IsSmi() && receiver->map()->has_fast_elements()) {
1649 MaybeObject* probe = 1677 MaybeObject* probe =
1650 StubCache::ComputeKeyedStoreSpecialized(*receiver); 1678 StubCache::ComputeKeyedStoreSpecialized(*receiver, strict_mode);
1651 stub = probe->IsFailure() ? 1679 stub = probe->IsFailure() ?
1652 NULL : Code::cast(probe->ToObjectUnchecked()); 1680 NULL : Code::cast(probe->ToObjectUnchecked());
1653 } 1681 }
1654 } 1682 }
1655 } 1683 }
1656 if (stub != NULL) set_target(stub); 1684 if (stub != NULL) set_target(stub);
1657 } 1685 }
1658 1686
1659 // Set the property. 1687 // Set the property.
1660 return Runtime::SetObjectProperty(object, key, value, NONE); 1688 return Runtime::SetObjectProperty(object, key, value, NONE, strict_mode);
1661 } 1689 }
1662 1690
1663 1691
1664 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, 1692 void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
1665 State state, 1693 State state,
1694 StrictModeFlag strict_mode,
1666 Handle<JSObject> receiver, 1695 Handle<JSObject> receiver,
1667 Handle<String> name, 1696 Handle<String> name,
1668 Handle<Object> value) { 1697 Handle<Object> value) {
1669 // Skip JSGlobalProxy. 1698 // Skip JSGlobalProxy.
1670 if (receiver->IsJSGlobalProxy()) return; 1699 if (receiver->IsJSGlobalProxy()) return;
1671 1700
1672 // Bail out if we didn't find a result. 1701 // Bail out if we didn't find a result.
1673 if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return; 1702 if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return;
1674 1703
1675 // If the property is read-only, we leave the IC in its current 1704 // If the property is read-only, we leave the IC in its current
1676 // state. 1705 // state.
1677 if (lookup->IsReadOnly()) return; 1706 if (lookup->IsReadOnly()) return;
1678 1707
1679 // If the property has a non-field type allowing map transitions 1708 // If the property has a non-field type allowing map transitions
1680 // where there is extra room in the object, we leave the IC in its 1709 // where there is extra room in the object, we leave the IC in its
1681 // current state. 1710 // current state.
1682 PropertyType type = lookup->type(); 1711 PropertyType type = lookup->type();
1683 1712
1684 // Compute the code stub for this store; used for rewriting to 1713 // Compute the code stub for this store; used for rewriting to
1685 // monomorphic state and making sure that the code stub is in the 1714 // monomorphic state and making sure that the code stub is in the
1686 // stub cache. 1715 // stub cache.
1687 MaybeObject* maybe_code = NULL; 1716 MaybeObject* maybe_code = NULL;
1688 Object* code = NULL; 1717 Object* code = NULL;
1689 1718
1690 switch (type) { 1719 switch (type) {
1691 case FIELD: { 1720 case FIELD: {
1692 maybe_code = StubCache::ComputeKeyedStoreField(*name, *receiver, 1721 maybe_code = StubCache::ComputeKeyedStoreField(
1693 lookup->GetFieldIndex()); 1722 *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode);
1694 break; 1723 break;
1695 } 1724 }
1696 case MAP_TRANSITION: { 1725 case MAP_TRANSITION: {
1697 if (lookup->GetAttributes() == NONE) { 1726 if (lookup->GetAttributes() == NONE) {
1698 HandleScope scope; 1727 HandleScope scope;
1699 ASSERT(type == MAP_TRANSITION); 1728 ASSERT(type == MAP_TRANSITION);
1700 Handle<Map> transition(lookup->GetTransitionMap()); 1729 Handle<Map> transition(lookup->GetTransitionMap());
1701 int index = transition->PropertyIndexFor(*name); 1730 int index = transition->PropertyIndexFor(*name);
1702 maybe_code = StubCache::ComputeKeyedStoreField(*name, *receiver, 1731 maybe_code = StubCache::ComputeKeyedStoreField(
1703 index, *transition); 1732 *name, *receiver, index, *transition, strict_mode);
1704 break; 1733 break;
1705 } 1734 }
1706 // fall through. 1735 // fall through.
1707 } 1736 }
1708 default: { 1737 default: {
1709 // Always rewrite to the generic case so that we do not 1738 // Always rewrite to the generic case so that we do not
1710 // repeatedly try to rewrite. 1739 // repeatedly try to rewrite.
1711 maybe_code = generic_stub(); 1740 maybe_code = (strict_mode == kStrictMode)
1741 ? generic_stub_strict()
1742 : generic_stub();
1712 break; 1743 break;
1713 } 1744 }
1714 } 1745 }
1715 1746
1716 // If we're unable to compute the stub (not enough memory left), we 1747 // If we're unable to compute the stub (not enough memory left), we
1717 // simply avoid updating the caches. 1748 // simply avoid updating the caches.
1718 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return; 1749 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
1719 1750
1720 // Patch the call site depending on the state of the cache. Make 1751 // Patch the call site depending on the state of the cache. Make
1721 // sure to always rewrite from monomorphic to megamorphic. 1752 // sure to always rewrite from monomorphic to megamorphic.
1722 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE); 1753 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE);
1723 if (state == UNINITIALIZED || state == PREMONOMORPHIC) { 1754 if (state == UNINITIALIZED || state == PREMONOMORPHIC) {
1724 set_target(Code::cast(code)); 1755 set_target(Code::cast(code));
1725 } else if (state == MONOMORPHIC) { 1756 } else if (state == MONOMORPHIC) {
1726 set_target(megamorphic_stub()); 1757 set_target((strict_mode == kStrictMode)
1758 ? megamorphic_stub_strict()
1759 : megamorphic_stub());
1727 } 1760 }
1728 1761
1729 #ifdef DEBUG 1762 #ifdef DEBUG
1730 TraceIC("KeyedStoreIC", name, state, target()); 1763 TraceIC("KeyedStoreIC", name, state, target());
1731 #endif 1764 #endif
1732 } 1765 }
1733 1766
1734 1767
1735 // ---------------------------------------------------------------------------- 1768 // ----------------------------------------------------------------------------
1736 // Static IC stub generators. 1769 // Static IC stub generators.
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
1817 } 1850 }
1818 1851
1819 1852
1820 // Used from ic-<arch>.cc. 1853 // Used from ic-<arch>.cc.
1821 MUST_USE_RESULT MaybeObject* StoreIC_Miss(Arguments args) { 1854 MUST_USE_RESULT MaybeObject* StoreIC_Miss(Arguments args) {
1822 NoHandleAllocation na; 1855 NoHandleAllocation na;
1823 ASSERT(args.length() == 3); 1856 ASSERT(args.length() == 3);
1824 StoreIC ic; 1857 StoreIC ic;
1825 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 1858 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1826 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); 1859 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
1827 return ic.Store(state, extra_ic_state, args.at<Object>(0), 1860 return ic.Store(state,
1828 args.at<String>(1), args.at<Object>(2)); 1861 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
1862 args.at<Object>(0),
1863 args.at<String>(1),
1864 args.at<Object>(2));
1829 } 1865 }
1830 1866
1831 1867
1832 MUST_USE_RESULT MaybeObject* StoreIC_ArrayLength(Arguments args) { 1868 MUST_USE_RESULT MaybeObject* StoreIC_ArrayLength(Arguments args) {
1833 NoHandleAllocation nha; 1869 NoHandleAllocation nha;
1834 1870
1835 ASSERT(args.length() == 2); 1871 ASSERT(args.length() == 2);
1836 JSObject* receiver = JSObject::cast(args[0]); 1872 JSObject* receiver = JSObject::cast(args[0]);
1837 Object* len = args[1]; 1873 Object* len = args[1];
1838 1874
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1882 return value; 1918 return value;
1883 } 1919 }
1884 1920
1885 1921
1886 // Used from ic-<arch>.cc. 1922 // Used from ic-<arch>.cc.
1887 MUST_USE_RESULT MaybeObject* KeyedStoreIC_Miss(Arguments args) { 1923 MUST_USE_RESULT MaybeObject* KeyedStoreIC_Miss(Arguments args) {
1888 NoHandleAllocation na; 1924 NoHandleAllocation na;
1889 ASSERT(args.length() == 3); 1925 ASSERT(args.length() == 3);
1890 KeyedStoreIC ic; 1926 KeyedStoreIC ic;
1891 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 1927 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1892 return ic.Store(state, args.at<Object>(0), args.at<Object>(1), 1928 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
1929 return ic.Store(state,
1930 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
1931 args.at<Object>(0),
1932 args.at<Object>(1),
1893 args.at<Object>(2)); 1933 args.at<Object>(2));
1894 } 1934 }
1895 1935
1896 1936
1897 void BinaryOpIC::patch(Code* code) { 1937 void BinaryOpIC::patch(Code* code) {
1898 set_target(code); 1938 set_target(code);
1899 } 1939 }
1900 1940
1901 1941
1902 const char* BinaryOpIC::GetName(TypeInfo type_info) { 1942 const char* BinaryOpIC::GetName(TypeInfo type_info) {
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after
2286 #undef ADDR 2326 #undef ADDR
2287 }; 2327 };
2288 2328
2289 2329
2290 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2330 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2291 return IC_utilities[id]; 2331 return IC_utilities[id];
2292 } 2332 }
2293 2333
2294 2334
2295 } } // namespace v8::internal 2335 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/ic-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698