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

Side by Side Diff: src/x64/stub-cache-x64.cc

Issue 110573004: Merge bleeding_edge 17696:18016. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 7 years 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
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 418 matching lines...) Expand 10 before | Expand all | Expand 10 after
429 // -- rsp[kFastApiCallArguments * 8 + 8] : last argument in the internal 429 // -- rsp[kFastApiCallArguments * 8 + 8] : last argument in the internal
430 // frame. 430 // frame.
431 // ----------------------------------- 431 // -----------------------------------
432 __ movq(scratch, StackOperandForReturnAddress(0)); 432 __ movq(scratch, StackOperandForReturnAddress(0));
433 __ movq(StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize), 433 __ movq(StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize),
434 scratch); 434 scratch);
435 __ addq(rsp, Immediate(kPointerSize * kFastApiCallArguments)); 435 __ addq(rsp, Immediate(kPointerSize * kFastApiCallArguments));
436 } 436 }
437 437
438 438
439 static void GenerateFastApiCallBody(MacroAssembler* masm,
440 const CallOptimization& optimization,
441 int argc,
442 bool restore_context);
443
444
439 // Generates call to API function. 445 // Generates call to API function.
440 static void GenerateFastApiCall(MacroAssembler* masm, 446 static void GenerateFastApiCall(MacroAssembler* masm,
441 const CallOptimization& optimization, 447 const CallOptimization& optimization,
442 int argc, 448 int argc) {
443 bool restore_context) {
444 // ----------- S t a t e -------------
445 // -- rsp[0] : return address
446 // -- rsp[8] - rsp[56] : FunctionCallbackInfo, incl.
447 // : object passing the type check
448 // (set by CheckPrototypes)
449 // -- rsp[64] : last argument
450 // -- ...
451 // -- rsp[(argc + 7) * 8] : first argument
452 // -- rsp[(argc + 8) * 8] : receiver
453 // -----------------------------------
454 typedef FunctionCallbackArguments FCA; 449 typedef FunctionCallbackArguments FCA;
455 StackArgumentsAccessor args(rsp, argc + kFastApiCallArguments); 450 StackArgumentsAccessor args(rsp, argc + kFastApiCallArguments);
456 451
457 // Save calling context. 452 // Save calling context.
458 int offset = argc + kFastApiCallArguments; 453 int offset = argc + kFastApiCallArguments;
459 __ movq(args.GetArgumentOperand(offset - FCA::kContextSaveIndex), rsi); 454 __ movq(args.GetArgumentOperand(offset - FCA::kContextSaveIndex), rsi);
460 455
461 // Get the function and setup the context. 456 // Get the function and setup the context.
462 Handle<JSFunction> function = optimization.constant_function(); 457 Handle<JSFunction> function = optimization.constant_function();
463 __ Move(rdi, function); 458 __ Move(rdi, function);
(...skipping 14 matching lines...) Expand all
478 __ movq(args.GetArgumentOperand(offset - FCA::kIsolateIndex), 473 __ movq(args.GetArgumentOperand(offset - FCA::kIsolateIndex),
479 kScratchRegister); 474 kScratchRegister);
480 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); 475 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
481 __ movq(args.GetArgumentOperand(offset - FCA::kReturnValueDefaultValueIndex), 476 __ movq(args.GetArgumentOperand(offset - FCA::kReturnValueDefaultValueIndex),
482 kScratchRegister); 477 kScratchRegister);
483 __ movq(args.GetArgumentOperand(offset - FCA::kReturnValueOffset), 478 __ movq(args.GetArgumentOperand(offset - FCA::kReturnValueOffset),
484 kScratchRegister); 479 kScratchRegister);
485 480
486 // Prepare arguments. 481 // Prepare arguments.
487 STATIC_ASSERT(kFastApiCallArguments == 7); 482 STATIC_ASSERT(kFastApiCallArguments == 7);
488 __ lea(rbx, Operand(rsp, 1 * kPointerSize)); 483 __ lea(rax, Operand(rsp, 1 * kPointerSize));
489 484
485 GenerateFastApiCallBody(masm, optimization, argc, false);
486 }
487
488
489 // Generate call to api function.
490 // This function uses push() to generate smaller, faster code than
491 // the version above. It is an optimization that should will be removed
492 // when api call ICs are generated in hydrogen.
493 static void GenerateFastApiCall(MacroAssembler* masm,
494 const CallOptimization& optimization,
495 Register receiver,
496 Register scratch1,
497 Register scratch2,
498 Register scratch3,
499 int argc,
500 Register* values) {
501 ASSERT(optimization.is_simple_api_call());
502
503 // Copy return value.
504 __ pop(scratch1);
505
506 // receiver
507 __ push(receiver);
508
509 // Write the arguments to stack frame.
510 for (int i = 0; i < argc; i++) {
511 Register arg = values[argc-1-i];
512 ASSERT(!receiver.is(arg));
513 ASSERT(!scratch1.is(arg));
514 ASSERT(!scratch2.is(arg));
515 ASSERT(!scratch3.is(arg));
516 __ push(arg);
517 }
518
519 typedef FunctionCallbackArguments FCA;
520
521 STATIC_ASSERT(FCA::kHolderIndex == 0);
522 STATIC_ASSERT(FCA::kIsolateIndex == 1);
523 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
524 STATIC_ASSERT(FCA::kReturnValueOffset == 3);
525 STATIC_ASSERT(FCA::kDataIndex == 4);
526 STATIC_ASSERT(FCA::kCalleeIndex == 5);
527 STATIC_ASSERT(FCA::kContextSaveIndex == 6);
528 STATIC_ASSERT(FCA::kArgsLength == 7);
529
530 // context save
531 __ push(rsi);
532
533 // Get the function and setup the context.
534 Handle<JSFunction> function = optimization.constant_function();
535 __ Move(scratch2, function);
536 __ push(scratch2);
537
538 Isolate* isolate = masm->isolate();
539 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
540 Handle<Object> call_data(api_call_info->data(), isolate);
541 // Push data from ExecutableAccessorInfo.
542 bool call_data_undefined = false;
543 if (isolate->heap()->InNewSpace(*call_data)) {
544 __ Move(scratch2, api_call_info);
545 __ movq(scratch3, FieldOperand(scratch2, CallHandlerInfo::kDataOffset));
546 } else if (call_data->IsUndefined()) {
547 call_data_undefined = true;
548 __ LoadRoot(scratch3, Heap::kUndefinedValueRootIndex);
549 } else {
550 __ Move(scratch3, call_data);
551 }
552 // call data
553 __ push(scratch3);
554 if (!call_data_undefined) {
555 __ LoadRoot(scratch3, Heap::kUndefinedValueRootIndex);
556 }
557 // return value
558 __ push(scratch3);
559 // return value default
560 __ push(scratch3);
561 // isolate
562 __ Move(scratch3,
563 ExternalReference::isolate_address(masm->isolate()));
564 __ push(scratch3);
565 // holder
566 __ push(receiver);
567
568 ASSERT(!scratch1.is(rax));
569 // store receiver address for GenerateFastApiCallBody
570 __ movq(rax, rsp);
571
572 // return address
573 __ push(scratch1);
574
575 GenerateFastApiCallBody(masm, optimization, argc, true);
576 }
577
578
579 static void GenerateFastApiCallBody(MacroAssembler* masm,
580 const CallOptimization& optimization,
581 int argc,
582 bool restore_context) {
583 // ----------- S t a t e -------------
584 // -- rsp[0] : return address
585 // -- rsp[8] - rsp[56] : FunctionCallbackInfo, incl.
586 // : object passing the type check
587 // (set by CheckPrototypes)
588 // -- rsp[64] : last argument
589 // -- ...
590 // -- rsp[(argc + 7) * 8] : first argument
591 // -- rsp[(argc + 8) * 8] : receiver
592 //
593 // rax : receiver address
594 // -----------------------------------
595 typedef FunctionCallbackArguments FCA;
596
597 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
490 // Function address is a foreign pointer outside V8's heap. 598 // Function address is a foreign pointer outside V8's heap.
491 Address function_address = v8::ToCData<Address>(api_call_info->callback()); 599 Address function_address = v8::ToCData<Address>(api_call_info->callback());
492 600
493 // Allocate the v8::Arguments structure in the arguments' space since 601 // Allocate the v8::Arguments structure in the arguments' space since
494 // it's not controlled by GC. 602 // it's not controlled by GC.
495 const int kApiStackSpace = 4; 603 const int kApiStackSpace = 4;
496 604
497 __ PrepareCallApiFunction(kApiStackSpace); 605 __ PrepareCallApiFunction(kApiStackSpace);
498 606
499 __ movq(StackSpaceOperand(0), rbx); // FunctionCallbackInfo::implicit_args_. 607 __ movq(StackSpaceOperand(0), rax); // FunctionCallbackInfo::implicit_args_.
500 __ addq(rbx, Immediate((argc + kFastApiCallArguments - 1) * kPointerSize)); 608 __ addq(rax, Immediate((argc + kFastApiCallArguments - 1) * kPointerSize));
501 __ movq(StackSpaceOperand(1), rbx); // FunctionCallbackInfo::values_. 609 __ movq(StackSpaceOperand(1), rax); // FunctionCallbackInfo::values_.
502 __ Set(StackSpaceOperand(2), argc); // FunctionCallbackInfo::length_. 610 __ Set(StackSpaceOperand(2), argc); // FunctionCallbackInfo::length_.
503 // FunctionCallbackInfo::is_construct_call_. 611 // FunctionCallbackInfo::is_construct_call_.
504 __ Set(StackSpaceOperand(3), 0); 612 __ Set(StackSpaceOperand(3), 0);
505 613
506 #if defined(__MINGW64__) || defined(_WIN64) 614 #if defined(__MINGW64__) || defined(_WIN64)
507 Register arguments_arg = rcx; 615 Register arguments_arg = rcx;
508 Register callback_arg = rdx; 616 Register callback_arg = rdx;
509 #else 617 #else
510 Register arguments_arg = rdi; 618 Register arguments_arg = rdi;
511 Register callback_arg = rsi; 619 Register callback_arg = rsi;
(...skipping 13 matching lines...) Expand all
525 __ CallApiFunctionAndReturn( 633 __ CallApiFunctionAndReturn(
526 function_address, 634 function_address,
527 thunk_address, 635 thunk_address,
528 callback_arg, 636 callback_arg,
529 argc + kFastApiCallArguments + 1, 637 argc + kFastApiCallArguments + 1,
530 return_value_operand, 638 return_value_operand,
531 restore_context ? &context_restore_operand : NULL); 639 restore_context ? &context_restore_operand : NULL);
532 } 640 }
533 641
534 642
535 // Generate call to api function.
536 static void GenerateFastApiCall(MacroAssembler* masm,
537 const CallOptimization& optimization,
538 Register receiver,
539 Register scratch,
540 int argc,
541 Register* values) {
542 ASSERT(optimization.is_simple_api_call());
543 ASSERT(!receiver.is(scratch));
544
545 const int fast_api_call_argc = argc + kFastApiCallArguments;
546 StackArgumentsAccessor args(rsp, fast_api_call_argc);
547 // argc + 1 is the argument number before FastApiCall arguments, 1 ~ receiver
548 const int kHolderIndex = argc + 1 +
549 kFastApiCallArguments - 1 - FunctionCallbackArguments::kHolderIndex;
550 __ movq(scratch, StackOperandForReturnAddress(0));
551 // Assign stack space for the call arguments and receiver.
552 __ subq(rsp, Immediate((fast_api_call_argc + 1) * kPointerSize));
553 __ movq(StackOperandForReturnAddress(0), scratch);
554 // Write holder to stack frame.
555 __ movq(args.GetArgumentOperand(kHolderIndex), receiver);
556 __ movq(args.GetReceiverOperand(), receiver);
557 // Write the arguments to stack frame.
558 for (int i = 0; i < argc; i++) {
559 ASSERT(!receiver.is(values[i]));
560 ASSERT(!scratch.is(values[i]));
561 __ movq(args.GetArgumentOperand(i + 1), values[i]);
562 }
563
564 GenerateFastApiCall(masm, optimization, argc, true);
565 }
566
567
568 class CallInterceptorCompiler BASE_EMBEDDED { 643 class CallInterceptorCompiler BASE_EMBEDDED {
569 public: 644 public:
570 CallInterceptorCompiler(StubCompiler* stub_compiler, 645 CallInterceptorCompiler(StubCompiler* stub_compiler,
571 const ParameterCount& arguments, 646 const ParameterCount& arguments,
572 Register name, 647 Register name,
573 Code::ExtraICState extra_ic_state) 648 Code::ExtraICState extra_ic_state)
574 : stub_compiler_(stub_compiler), 649 : stub_compiler_(stub_compiler),
575 arguments_(arguments), 650 arguments_(arguments),
576 name_(name), 651 name_(name),
577 extra_ic_state_(extra_ic_state) {} 652 extra_ic_state_(extra_ic_state) {}
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
668 } else { 743 } else {
669 // CheckPrototypes has a side effect of fetching a 'holder' 744 // CheckPrototypes has a side effect of fetching a 'holder'
670 // for API (object which is instanceof for the signature). It's 745 // for API (object which is instanceof for the signature). It's
671 // safe to omit it here, as if present, it should be fetched 746 // safe to omit it here, as if present, it should be fetched
672 // by the previous CheckPrototypes. 747 // by the previous CheckPrototypes.
673 ASSERT(depth2 == kInvalidProtoDepth); 748 ASSERT(depth2 == kInvalidProtoDepth);
674 } 749 }
675 750
676 // Invoke function. 751 // Invoke function.
677 if (can_do_fast_api_call) { 752 if (can_do_fast_api_call) {
678 GenerateFastApiCall(masm, optimization, arguments_.immediate(), false); 753 GenerateFastApiCall(masm, optimization, arguments_.immediate());
679 } else { 754 } else {
680 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) 755 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
681 ? CALL_AS_FUNCTION 756 ? CALL_AS_FUNCTION
682 : CALL_AS_METHOD; 757 : CALL_AS_METHOD;
683 Handle<JSFunction> fun = optimization.constant_function(); 758 Handle<JSFunction> fun = optimization.constant_function();
684 ParameterCount expected(fun); 759 ParameterCount expected(fun);
685 __ InvokeFunction(fun, expected, arguments_, 760 __ InvokeFunction(fun, expected, arguments_,
686 JUMP_FUNCTION, NullCallWrapper(), call_kind); 761 JUMP_FUNCTION, NullCallWrapper(), call_kind);
687 } 762 }
688 763
(...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after
1193 // If we've skipped any global objects, it's not enough to verify that 1268 // If we've skipped any global objects, it's not enough to verify that
1194 // their maps haven't changed. We also need to check that the property 1269 // their maps haven't changed. We also need to check that the property
1195 // cell for the property is still empty. 1270 // cell for the property is still empty.
1196 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); 1271 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss);
1197 1272
1198 // Return the register containing the holder. 1273 // Return the register containing the holder.
1199 return reg; 1274 return reg;
1200 } 1275 }
1201 1276
1202 1277
1203 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, 1278 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
1204 Label* success,
1205 Label* miss) {
1206 if (!miss->is_unused()) { 1279 if (!miss->is_unused()) {
1207 __ jmp(success); 1280 Label success;
1281 __ jmp(&success);
1208 __ bind(miss); 1282 __ bind(miss);
1209 TailCallBuiltin(masm(), MissBuiltin(kind())); 1283 TailCallBuiltin(masm(), MissBuiltin(kind()));
1284 __ bind(&success);
1210 } 1285 }
1211 } 1286 }
1212 1287
1213 1288
1214 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, 1289 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
1215 Label* success,
1216 Label* miss) {
1217 if (!miss->is_unused()) { 1290 if (!miss->is_unused()) {
1218 __ jmp(success); 1291 Label success;
1292 __ jmp(&success);
1219 GenerateRestoreName(masm(), miss, name); 1293 GenerateRestoreName(masm(), miss, name);
1220 TailCallBuiltin(masm(), MissBuiltin(kind())); 1294 TailCallBuiltin(masm(), MissBuiltin(kind()));
1295 __ bind(&success);
1221 } 1296 }
1222 } 1297 }
1223 1298
1224 1299
1225 Register LoadStubCompiler::CallbackHandlerFrontend( 1300 Register LoadStubCompiler::CallbackHandlerFrontend(
1226 Handle<JSObject> object, 1301 Handle<Object> object,
1227 Register object_reg, 1302 Register object_reg,
1228 Handle<JSObject> holder, 1303 Handle<JSObject> holder,
1229 Handle<Name> name, 1304 Handle<Name> name,
1230 Label* success,
1231 Handle<Object> callback) { 1305 Handle<Object> callback) {
1232 Label miss; 1306 Label miss;
1233 1307
1234 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); 1308 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss);
1235 1309
1236 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { 1310 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) {
1237 ASSERT(!reg.is(scratch2())); 1311 ASSERT(!reg.is(scratch2()));
1238 ASSERT(!reg.is(scratch3())); 1312 ASSERT(!reg.is(scratch3()));
1239 ASSERT(!reg.is(scratch4())); 1313 ASSERT(!reg.is(scratch4()));
1240 1314
(...skipping 20 matching lines...) Expand all
1261 NameDictionary::kElementsStartIndex * kPointerSize; 1335 NameDictionary::kElementsStartIndex * kPointerSize;
1262 const int kValueOffset = kElementsStartOffset + kPointerSize; 1336 const int kValueOffset = kElementsStartOffset + kPointerSize;
1263 __ movq(scratch2(), 1337 __ movq(scratch2(),
1264 Operand(dictionary, index, times_pointer_size, 1338 Operand(dictionary, index, times_pointer_size,
1265 kValueOffset - kHeapObjectTag)); 1339 kValueOffset - kHeapObjectTag));
1266 __ movq(scratch3(), callback, RelocInfo::EMBEDDED_OBJECT); 1340 __ movq(scratch3(), callback, RelocInfo::EMBEDDED_OBJECT);
1267 __ cmpq(scratch2(), scratch3()); 1341 __ cmpq(scratch2(), scratch3());
1268 __ j(not_equal, &miss); 1342 __ j(not_equal, &miss);
1269 } 1343 }
1270 1344
1271 HandlerFrontendFooter(name, success, &miss); 1345 HandlerFrontendFooter(name, &miss);
1272 return reg; 1346 return reg;
1273 } 1347 }
1274 1348
1275 1349
1276 void LoadStubCompiler::GenerateLoadField(Register reg, 1350 void LoadStubCompiler::GenerateLoadField(Register reg,
1277 Handle<JSObject> holder, 1351 Handle<JSObject> holder,
1278 PropertyIndex field, 1352 PropertyIndex field,
1279 Representation representation) { 1353 Representation representation) {
1280 if (!reg.is(receiver())) __ movq(receiver(), reg); 1354 if (!reg.is(receiver())) __ movq(receiver(), reg);
1281 if (kind() == Code::LOAD_IC) { 1355 if (kind() == Code::LOAD_IC) {
1282 LoadFieldStub stub(field.is_inobject(holder), 1356 LoadFieldStub stub(field.is_inobject(holder),
1283 field.translate(holder), 1357 field.translate(holder),
1284 representation); 1358 representation);
1285 GenerateTailCall(masm(), stub.GetCode(isolate())); 1359 GenerateTailCall(masm(), stub.GetCode(isolate()));
1286 } else { 1360 } else {
1287 KeyedLoadFieldStub stub(field.is_inobject(holder), 1361 KeyedLoadFieldStub stub(field.is_inobject(holder),
1288 field.translate(holder), 1362 field.translate(holder),
1289 representation); 1363 representation);
1290 GenerateTailCall(masm(), stub.GetCode(isolate())); 1364 GenerateTailCall(masm(), stub.GetCode(isolate()));
1291 } 1365 }
1292 } 1366 }
1293 1367
1294 1368
1295 void LoadStubCompiler::GenerateLoadCallback( 1369 void LoadStubCompiler::GenerateLoadCallback(
1296 const CallOptimization& call_optimization) { 1370 const CallOptimization& call_optimization) {
1297 GenerateFastApiCall( 1371 GenerateFastApiCall(
1298 masm(), call_optimization, receiver(), scratch3(), 0, NULL); 1372 masm(), call_optimization, receiver(),
1373 scratch1(), scratch2(), name(), 0, NULL);
1299 } 1374 }
1300 1375
1301 1376
1302 void LoadStubCompiler::GenerateLoadCallback( 1377 void LoadStubCompiler::GenerateLoadCallback(
1303 Register reg, 1378 Register reg,
1304 Handle<ExecutableAccessorInfo> callback) { 1379 Handle<ExecutableAccessorInfo> callback) {
1305 // Insert additional parameters into the stack frame above return address. 1380 // Insert additional parameters into the stack frame above return address.
1306 ASSERT(!scratch4().is(reg)); 1381 ASSERT(!scratch4().is(reg));
1307 __ PopReturnAddressTo(scratch4()); 1382 __ PopReturnAddressTo(scratch4());
1308 1383
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1382 1457
1383 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { 1458 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) {
1384 // Return the constant value. 1459 // Return the constant value.
1385 __ Move(rax, value); 1460 __ Move(rax, value);
1386 __ ret(0); 1461 __ ret(0);
1387 } 1462 }
1388 1463
1389 1464
1390 void LoadStubCompiler::GenerateLoadInterceptor( 1465 void LoadStubCompiler::GenerateLoadInterceptor(
1391 Register holder_reg, 1466 Register holder_reg,
1392 Handle<JSObject> object, 1467 Handle<Object> object,
1393 Handle<JSObject> interceptor_holder, 1468 Handle<JSObject> interceptor_holder,
1394 LookupResult* lookup, 1469 LookupResult* lookup,
1395 Handle<Name> name) { 1470 Handle<Name> name) {
1396 ASSERT(interceptor_holder->HasNamedInterceptor()); 1471 ASSERT(interceptor_holder->HasNamedInterceptor());
1397 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); 1472 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
1398 1473
1399 // So far the most popular follow ups for interceptor loads are FIELD 1474 // So far the most popular follow ups for interceptor loads are FIELD
1400 // and CALLBACKS, so inline only them, other cases may be added 1475 // and CALLBACKS, so inline only them, other cases may be added
1401 // later. 1476 // later.
1402 bool compile_followup_inline = false; 1477 bool compile_followup_inline = false;
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
1589 ? CALL_AS_FUNCTION 1664 ? CALL_AS_FUNCTION
1590 : CALL_AS_METHOD; 1665 : CALL_AS_METHOD;
1591 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, 1666 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
1592 NullCallWrapper(), call_kind); 1667 NullCallWrapper(), call_kind);
1593 1668
1594 // Handle call cache miss. 1669 // Handle call cache miss.
1595 __ bind(&miss); 1670 __ bind(&miss);
1596 GenerateMissBranch(); 1671 GenerateMissBranch();
1597 1672
1598 // Return the generated code. 1673 // Return the generated code.
1599 return GetCode(Code::FIELD, name); 1674 return GetCode(Code::FAST, name);
1600 } 1675 }
1601 1676
1602 1677
1603 Handle<Code> CallStubCompiler::CompileArrayCodeCall( 1678 Handle<Code> CallStubCompiler::CompileArrayCodeCall(
1604 Handle<Object> object, 1679 Handle<Object> object,
1605 Handle<JSObject> holder, 1680 Handle<JSObject> holder,
1606 Handle<Cell> cell, 1681 Handle<Cell> cell,
1607 Handle<JSFunction> function, 1682 Handle<JSFunction> function,
1608 Handle<String> name, 1683 Handle<String> name,
1609 Code::StubType type) { 1684 Code::StubType type) {
(...skipping 12 matching lines...) Expand all
1622 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, 1697 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
1623 name, &miss); 1698 name, &miss);
1624 } else { 1699 } else {
1625 ASSERT(cell->value() == *function); 1700 ASSERT(cell->value() == *function);
1626 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 1701 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
1627 &miss); 1702 &miss);
1628 GenerateLoadFunctionFromCell(cell, function, &miss); 1703 GenerateLoadFunctionFromCell(cell, function, &miss);
1629 } 1704 }
1630 1705
1631 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); 1706 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite();
1632 site->set_transition_info(Smi::FromInt(GetInitialFastElementsKind())); 1707 site->SetElementsKind(GetInitialFastElementsKind());
1633 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); 1708 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site);
1634 __ movq(rax, Immediate(argc)); 1709 __ movq(rax, Immediate(argc));
1635 __ Move(rbx, site_feedback_cell); 1710 __ Move(rbx, site_feedback_cell);
1636 __ Move(rdi, function); 1711 __ Move(rdi, function);
1637 1712
1638 ArrayConstructorStub stub(isolate()); 1713 ArrayConstructorStub stub(isolate());
1639 __ TailCallStub(&stub); 1714 __ TailCallStub(&stub);
1640 1715
1641 __ bind(&miss); 1716 __ bind(&miss);
1642 GenerateMissBranch(); 1717 GenerateMissBranch();
(...skipping 11 matching lines...) Expand all
1654 Handle<String> name, 1729 Handle<String> name,
1655 Code::StubType type) { 1730 Code::StubType type) {
1656 // ----------- S t a t e ------------- 1731 // ----------- S t a t e -------------
1657 // -- rcx : name 1732 // -- rcx : name
1658 // -- rsp[0] : return address 1733 // -- rsp[0] : return address
1659 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) 1734 // -- rsp[(argc - n) * 8] : arg[n] (zero-based)
1660 // -- ... 1735 // -- ...
1661 // -- rsp[(argc + 1) * 8] : receiver 1736 // -- rsp[(argc + 1) * 8] : receiver
1662 // ----------------------------------- 1737 // -----------------------------------
1663 1738
1664 // If object is not an array, bail out to regular call. 1739 // If object is not an array or is observed, bail out to regular call.
1665 if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); 1740 if (!object->IsJSArray() ||
1741 !cell.is_null() ||
1742 Handle<JSArray>::cast(object)->map()->is_observed()) {
1743 return Handle<Code>::null();
1744 }
1666 1745
1667 Label miss; 1746 Label miss;
1668 GenerateNameCheck(name, &miss); 1747 GenerateNameCheck(name, &miss);
1669 1748
1670 const int argc = arguments().immediate(); 1749 const int argc = arguments().immediate();
1671 StackArgumentsAccessor args(rsp, argc); 1750 StackArgumentsAccessor args(rsp, argc);
1672 __ movq(rdx, args.GetReceiverOperand()); 1751 __ movq(rdx, args.GetReceiverOperand());
1673 1752
1674 // Check that the receiver isn't a smi. 1753 // Check that the receiver isn't a smi.
1675 __ JumpIfSmi(rdx, &miss); 1754 __ JumpIfSmi(rdx, &miss);
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
1905 Handle<String> name, 1984 Handle<String> name,
1906 Code::StubType type) { 1985 Code::StubType type) {
1907 // ----------- S t a t e ------------- 1986 // ----------- S t a t e -------------
1908 // -- rcx : name 1987 // -- rcx : name
1909 // -- rsp[0] : return address 1988 // -- rsp[0] : return address
1910 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) 1989 // -- rsp[(argc - n) * 8] : arg[n] (zero-based)
1911 // -- ... 1990 // -- ...
1912 // -- rsp[(argc + 1) * 8] : receiver 1991 // -- rsp[(argc + 1) * 8] : receiver
1913 // ----------------------------------- 1992 // -----------------------------------
1914 1993
1915 // If object is not an array, bail out to regular call. 1994 // If object is not an array or is observed, bail out to regular call.
1916 if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); 1995 if (!object->IsJSArray() ||
1996 !cell.is_null() ||
1997 Handle<JSArray>::cast(object)->map()->is_observed()) {
1998 return Handle<Code>::null();
1999 }
1917 2000
1918 Label miss, return_undefined, call_builtin; 2001 Label miss, return_undefined, call_builtin;
1919 GenerateNameCheck(name, &miss); 2002 GenerateNameCheck(name, &miss);
1920 2003
1921 const int argc = arguments().immediate(); 2004 const int argc = arguments().immediate();
1922 StackArgumentsAccessor args(rsp, argc); 2005 StackArgumentsAccessor args(rsp, argc);
1923 __ movq(rdx, args.GetReceiverOperand()); 2006 __ movq(rdx, args.GetReceiverOperand());
1924 2007
1925 // Check that the receiver isn't a smi. 2008 // Check that the receiver isn't a smi.
1926 __ JumpIfSmi(rdx, &miss); 2009 __ JumpIfSmi(rdx, &miss);
(...skipping 560 matching lines...) Expand 10 before | Expand all | Expand 10 after
2487 2570
2488 // Check that the maps haven't changed and find a Holder as a side effect. 2571 // Check that the maps haven't changed and find a Holder as a side effect.
2489 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, 2572 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
2490 name, depth, &miss); 2573 name, depth, &miss);
2491 2574
2492 // Move the return address on top of the stack. 2575 // Move the return address on top of the stack.
2493 __ movq(rax, 2576 __ movq(rax,
2494 StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize)); 2577 StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize));
2495 __ movq(StackOperandForReturnAddress(0), rax); 2578 __ movq(StackOperandForReturnAddress(0), rax);
2496 2579
2497 GenerateFastApiCall(masm(), optimization, argc, false); 2580 GenerateFastApiCall(masm(), optimization, argc);
2498 2581
2499 __ bind(&miss); 2582 __ bind(&miss);
2500 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); 2583 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
2501 2584
2502 __ bind(&miss_before_stack_reserved); 2585 __ bind(&miss_before_stack_reserved);
2503 GenerateMissBranch(); 2586 GenerateMissBranch();
2504 2587
2505 // Return the generated code. 2588 // Return the generated code.
2506 return GetCode(function); 2589 return GetCode(function);
2507 } 2590 }
2508 2591
2509 2592
2593 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
2594 Label success;
2595 // Check that the object is a boolean.
2596 __ CompareRoot(object, Heap::kTrueValueRootIndex);
2597 __ j(equal, &success);
2598 __ CompareRoot(object, Heap::kFalseValueRootIndex);
2599 __ j(not_equal, miss);
2600 __ bind(&success);
2601 }
2602
2603
2510 void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object, 2604 void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
2511 Handle<JSObject> holder, 2605 Handle<JSObject> holder,
2512 Handle<Name> name, 2606 Handle<Name> name,
2513 CheckType check, 2607 CheckType check) {
2514 Label* success) {
2515 // ----------- S t a t e ------------- 2608 // ----------- S t a t e -------------
2516 // rcx : function name 2609 // rcx : function name
2517 // rsp[0] : return address 2610 // rsp[0] : return address
2518 // rsp[8] : argument argc 2611 // rsp[8] : argument argc
2519 // rsp[16] : argument argc - 1 2612 // rsp[16] : argument argc - 1
2520 // ... 2613 // ...
2521 // rsp[argc * 8] : argument 1 2614 // rsp[argc * 8] : argument 1
2522 // rsp[(argc + 1) * 8] : argument 0 = receiver 2615 // rsp[(argc + 1) * 8] : argument 0 = receiver
2523 // ----------------------------------- 2616 // -----------------------------------
2524 Label miss; 2617 Label miss;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
2586 __ bind(&fast); 2679 __ bind(&fast);
2587 // Check that the maps starting from the prototype haven't changed. 2680 // Check that the maps starting from the prototype haven't changed.
2588 GenerateDirectLoadGlobalFunctionPrototype( 2681 GenerateDirectLoadGlobalFunctionPrototype(
2589 masm(), Context::NUMBER_FUNCTION_INDEX, rax, &miss); 2682 masm(), Context::NUMBER_FUNCTION_INDEX, rax, &miss);
2590 CheckPrototypes( 2683 CheckPrototypes(
2591 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), 2684 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))),
2592 rax, holder, rbx, rdx, rdi, name, &miss); 2685 rax, holder, rbx, rdx, rdi, name, &miss);
2593 break; 2686 break;
2594 } 2687 }
2595 case BOOLEAN_CHECK: { 2688 case BOOLEAN_CHECK: {
2596 Label fast; 2689 GenerateBooleanCheck(rdx, &miss);
2597 // Check that the object is a boolean.
2598 __ CompareRoot(rdx, Heap::kTrueValueRootIndex);
2599 __ j(equal, &fast);
2600 __ CompareRoot(rdx, Heap::kFalseValueRootIndex);
2601 __ j(not_equal, &miss);
2602 __ bind(&fast);
2603 // Check that the maps starting from the prototype haven't changed. 2690 // Check that the maps starting from the prototype haven't changed.
2604 GenerateDirectLoadGlobalFunctionPrototype( 2691 GenerateDirectLoadGlobalFunctionPrototype(
2605 masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss); 2692 masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss);
2606 CheckPrototypes( 2693 CheckPrototypes(
2607 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), 2694 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))),
2608 rax, holder, rbx, rdx, rdi, name, &miss); 2695 rax, holder, rbx, rdx, rdi, name, &miss);
2609 break; 2696 break;
2610 } 2697 }
2611 } 2698 }
2612 2699
2613 __ jmp(success); 2700 Label success;
2701 __ jmp(&success);
2614 2702
2615 // Handle call cache miss. 2703 // Handle call cache miss.
2616 __ bind(&miss); 2704 __ bind(&miss);
2617 GenerateMissBranch(); 2705 GenerateMissBranch();
2706
2707 __ bind(&success);
2618 } 2708 }
2619 2709
2620 2710
2621 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { 2711 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) {
2622 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2712 CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2623 ? CALL_AS_FUNCTION 2713 ? CALL_AS_FUNCTION
2624 : CALL_AS_METHOD; 2714 : CALL_AS_METHOD;
2625 ParameterCount expected(function); 2715 ParameterCount expected(function);
2626 __ InvokeFunction(function, expected, arguments(), 2716 __ InvokeFunction(function, expected, arguments(),
2627 JUMP_FUNCTION, NullCallWrapper(), call_kind); 2717 JUMP_FUNCTION, NullCallWrapper(), call_kind);
2628 } 2718 }
2629 2719
2630 2720
2631 Handle<Code> CallStubCompiler::CompileCallConstant( 2721 Handle<Code> CallStubCompiler::CompileCallConstant(
2632 Handle<Object> object, 2722 Handle<Object> object,
2633 Handle<JSObject> holder, 2723 Handle<JSObject> holder,
2634 Handle<Name> name, 2724 Handle<Name> name,
2635 CheckType check, 2725 CheckType check,
2636 Handle<JSFunction> function) { 2726 Handle<JSFunction> function) {
2637 if (HasCustomCallGenerator(function)) { 2727 if (HasCustomCallGenerator(function)) {
2638 Handle<Code> code = CompileCustomCall(object, holder, 2728 Handle<Code> code = CompileCustomCall(object, holder,
2639 Handle<PropertyCell>::null(), 2729 Handle<PropertyCell>::null(),
2640 function, Handle<String>::cast(name), 2730 function, Handle<String>::cast(name),
2641 Code::CONSTANT); 2731 Code::FAST);
2642 // A null handle means bail out to the regular compiler code below. 2732 // A null handle means bail out to the regular compiler code below.
2643 if (!code.is_null()) return code; 2733 if (!code.is_null()) return code;
2644 } 2734 }
2645 2735
2646 Label success; 2736 CompileHandlerFrontend(object, holder, name, check);
2647
2648 CompileHandlerFrontend(object, holder, name, check, &success);
2649 __ bind(&success);
2650 CompileHandlerBackend(function); 2737 CompileHandlerBackend(function);
2651 2738
2652 // Return the generated code. 2739 // Return the generated code.
2653 return GetCode(function); 2740 return GetCode(function);
2654 } 2741 }
2655 2742
2656 2743
2657 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, 2744 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
2658 Handle<JSObject> holder, 2745 Handle<JSObject> holder,
2659 Handle<Name> name) { 2746 Handle<Name> name) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
2702 ? CALL_AS_FUNCTION 2789 ? CALL_AS_FUNCTION
2703 : CALL_AS_METHOD; 2790 : CALL_AS_METHOD;
2704 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, 2791 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
2705 NullCallWrapper(), call_kind); 2792 NullCallWrapper(), call_kind);
2706 2793
2707 // Handle load cache miss. 2794 // Handle load cache miss.
2708 __ bind(&miss); 2795 __ bind(&miss);
2709 GenerateMissBranch(); 2796 GenerateMissBranch();
2710 2797
2711 // Return the generated code. 2798 // Return the generated code.
2712 return GetCode(Code::INTERCEPTOR, name); 2799 return GetCode(Code::FAST, name);
2713 } 2800 }
2714 2801
2715 2802
2716 Handle<Code> CallStubCompiler::CompileCallGlobal( 2803 Handle<Code> CallStubCompiler::CompileCallGlobal(
2717 Handle<JSObject> object, 2804 Handle<JSObject> object,
2718 Handle<GlobalObject> holder, 2805 Handle<GlobalObject> holder,
2719 Handle<PropertyCell> cell, 2806 Handle<PropertyCell> cell,
2720 Handle<JSFunction> function, 2807 Handle<JSFunction> function,
2721 Handle<Name> name) { 2808 Handle<Name> name) {
2722 // ----------- S t a t e ------------- 2809 // ----------- S t a t e -------------
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2775 // Return the generated code. 2862 // Return the generated code.
2776 return GetCode(Code::NORMAL, name); 2863 return GetCode(Code::NORMAL, name);
2777 } 2864 }
2778 2865
2779 2866
2780 Handle<Code> StoreStubCompiler::CompileStoreCallback( 2867 Handle<Code> StoreStubCompiler::CompileStoreCallback(
2781 Handle<JSObject> object, 2868 Handle<JSObject> object,
2782 Handle<JSObject> holder, 2869 Handle<JSObject> holder,
2783 Handle<Name> name, 2870 Handle<Name> name,
2784 Handle<ExecutableAccessorInfo> callback) { 2871 Handle<ExecutableAccessorInfo> callback) {
2785 Label success; 2872 HandlerFrontend(object, receiver(), holder, name);
2786 HandlerFrontend(object, receiver(), holder, name, &success);
2787 __ bind(&success);
2788 2873
2789 __ PopReturnAddressTo(scratch1()); 2874 __ PopReturnAddressTo(scratch1());
2790 __ push(receiver()); 2875 __ push(receiver());
2791 __ Push(callback); // callback info 2876 __ Push(callback); // callback info
2792 __ Push(name); 2877 __ Push(name);
2793 __ push(value()); 2878 __ push(value());
2794 __ PushReturnAddressFrom(scratch1()); 2879 __ PushReturnAddressFrom(scratch1());
2795 2880
2796 // Do tail-call to the runtime system. 2881 // Do tail-call to the runtime system.
2797 ExternalReference store_callback_property = 2882 ExternalReference store_callback_property =
2798 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); 2883 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
2799 __ TailCallExternalReference(store_callback_property, 4, 1); 2884 __ TailCallExternalReference(store_callback_property, 4, 1);
2800 2885
2801 // Return the generated code. 2886 // Return the generated code.
2802 return GetCode(kind(), Code::CALLBACKS, name); 2887 return GetCode(kind(), Code::FAST, name);
2803 } 2888 }
2804 2889
2805 2890
2806 Handle<Code> StoreStubCompiler::CompileStoreCallback( 2891 Handle<Code> StoreStubCompiler::CompileStoreCallback(
2807 Handle<JSObject> object, 2892 Handle<JSObject> object,
2808 Handle<JSObject> holder, 2893 Handle<JSObject> holder,
2809 Handle<Name> name, 2894 Handle<Name> name,
2810 const CallOptimization& call_optimization) { 2895 const CallOptimization& call_optimization) {
2811 Label success; 2896 HandlerFrontend(object, receiver(), holder, name);
2812 HandlerFrontend(object, receiver(), holder, name, &success);
2813 __ bind(&success);
2814 2897
2815 Register values[] = { value() }; 2898 Register values[] = { value() };
2816 GenerateFastApiCall( 2899 GenerateFastApiCall(
2817 masm(), call_optimization, receiver(), scratch3(), 1, values); 2900 masm(), call_optimization, receiver(), scratch1(),
2901 scratch2(), this->name(), 1, values);
2818 2902
2819 // Return the generated code. 2903 // Return the generated code.
2820 return GetCode(kind(), Code::CALLBACKS, name); 2904 return GetCode(kind(), Code::FAST, name);
2821 } 2905 }
2822 2906
2823 2907
2824 #undef __ 2908 #undef __
2825 #define __ ACCESS_MASM(masm) 2909 #define __ ACCESS_MASM(masm)
2826 2910
2827 2911
2828 void StoreStubCompiler::GenerateStoreViaSetter( 2912 void StoreStubCompiler::GenerateStoreViaSetter(
2829 MacroAssembler* masm, 2913 MacroAssembler* masm,
2830 Handle<JSFunction> setter) { 2914 Handle<JSFunction> setter) {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
2877 __ push(value()); 2961 __ push(value());
2878 __ Push(Smi::FromInt(strict_mode())); 2962 __ Push(Smi::FromInt(strict_mode()));
2879 __ PushReturnAddressFrom(scratch1()); 2963 __ PushReturnAddressFrom(scratch1());
2880 2964
2881 // Do tail-call to the runtime system. 2965 // Do tail-call to the runtime system.
2882 ExternalReference store_ic_property = 2966 ExternalReference store_ic_property =
2883 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); 2967 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate());
2884 __ TailCallExternalReference(store_ic_property, 4, 1); 2968 __ TailCallExternalReference(store_ic_property, 4, 1);
2885 2969
2886 // Return the generated code. 2970 // Return the generated code.
2887 return GetCode(kind(), Code::INTERCEPTOR, name); 2971 return GetCode(kind(), Code::FAST, name);
2888 } 2972 }
2889 2973
2890 2974
2891 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( 2975 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
2892 MapHandleList* receiver_maps, 2976 MapHandleList* receiver_maps,
2893 CodeHandleList* handler_stubs, 2977 CodeHandleList* handler_stubs,
2894 MapHandleList* transitioned_maps) { 2978 MapHandleList* transitioned_maps) {
2895 Label miss; 2979 Label miss;
2896 __ JumpIfSmi(receiver(), &miss, Label::kNear); 2980 __ JumpIfSmi(receiver(), &miss, Label::kNear);
2897 2981
(...skipping 19 matching lines...) Expand all
2917 3001
2918 TailCallBuiltin(masm(), MissBuiltin(kind())); 3002 TailCallBuiltin(masm(), MissBuiltin(kind()));
2919 3003
2920 // Return the generated code. 3004 // Return the generated code.
2921 return GetICCode( 3005 return GetICCode(
2922 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); 3006 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
2923 } 3007 }
2924 3008
2925 3009
2926 Handle<Code> LoadStubCompiler::CompileLoadNonexistent( 3010 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
2927 Handle<JSObject> object, 3011 Handle<Object> object,
2928 Handle<JSObject> last, 3012 Handle<JSObject> last,
2929 Handle<Name> name, 3013 Handle<Name> name,
2930 Handle<JSGlobalObject> global) { 3014 Handle<JSGlobalObject> global) {
2931 Label success; 3015 NonexistentHandlerFrontend(object, last, name, global);
2932 3016
2933 NonexistentHandlerFrontend(object, last, name, &success, global);
2934
2935 __ bind(&success);
2936 // Return undefined if maps of the full prototype chain are still the 3017 // Return undefined if maps of the full prototype chain are still the
2937 // same and no global property with this name contains a value. 3018 // same and no global property with this name contains a value.
2938 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 3019 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
2939 __ ret(0); 3020 __ ret(0);
2940 3021
2941 // Return the generated code. 3022 // Return the generated code.
2942 return GetCode(kind(), Code::NONEXISTENT, name); 3023 return GetCode(kind(), Code::FAST, name);
2943 } 3024 }
2944 3025
2945 3026
2946 Register* LoadStubCompiler::registers() { 3027 Register* LoadStubCompiler::registers() {
2947 // receiver, name, scratch1, scratch2, scratch3, scratch4. 3028 // receiver, name, scratch1, scratch2, scratch3, scratch4.
2948 static Register registers[] = { rax, rcx, rdx, rbx, rdi, r8 }; 3029 static Register registers[] = { rax, rcx, rdx, rbx, rdi, r8 };
2949 return registers; 3030 return registers;
2950 } 3031 }
2951 3032
2952 3033
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
3020 } 3101 }
3021 __ ret(0); 3102 __ ret(0);
3022 } 3103 }
3023 3104
3024 3105
3025 #undef __ 3106 #undef __
3026 #define __ ACCESS_MASM(masm()) 3107 #define __ ACCESS_MASM(masm())
3027 3108
3028 3109
3029 Handle<Code> LoadStubCompiler::CompileLoadGlobal( 3110 Handle<Code> LoadStubCompiler::CompileLoadGlobal(
3030 Handle<JSObject> object, 3111 Handle<Object> object,
3031 Handle<GlobalObject> global, 3112 Handle<GlobalObject> global,
3032 Handle<PropertyCell> cell, 3113 Handle<PropertyCell> cell,
3033 Handle<Name> name, 3114 Handle<Name> name,
3034 bool is_dont_delete) { 3115 bool is_dont_delete) {
3035 Label success, miss; 3116 Label miss;
3036 // TODO(verwaest): Directly store to rax. Currently we cannot do this, since 3117 // TODO(verwaest): Directly store to rax. Currently we cannot do this, since
3037 // rax is used as receiver(), which we would otherwise clobber before a 3118 // rax is used as receiver(), which we would otherwise clobber before a
3038 // potential miss. 3119 // potential miss.
3039 HandlerFrontendHeader(object, receiver(), global, name, &miss); 3120 HandlerFrontendHeader(object, receiver(), global, name, &miss);
3040 3121
3041 // Get the value from the cell. 3122 // Get the value from the cell.
3042 __ Move(rbx, cell); 3123 __ Move(rbx, cell);
3043 __ movq(rbx, FieldOperand(rbx, PropertyCell::kValueOffset)); 3124 __ movq(rbx, FieldOperand(rbx, PropertyCell::kValueOffset));
3044 3125
3045 // Check for deleted property if property can actually be deleted. 3126 // Check for deleted property if property can actually be deleted.
3046 if (!is_dont_delete) { 3127 if (!is_dont_delete) {
3047 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); 3128 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
3048 __ j(equal, &miss); 3129 __ j(equal, &miss);
3049 } else if (FLAG_debug_code) { 3130 } else if (FLAG_debug_code) {
3050 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); 3131 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
3051 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); 3132 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole);
3052 } 3133 }
3053 3134
3054 HandlerFrontendFooter(name, &success, &miss); 3135 HandlerFrontendFooter(name, &miss);
3055 __ bind(&success);
3056 3136
3057 Counters* counters = isolate()->counters(); 3137 Counters* counters = isolate()->counters();
3058 __ IncrementCounter(counters->named_load_global_stub(), 1); 3138 __ IncrementCounter(counters->named_load_global_stub(), 1);
3059 __ movq(rax, rbx); 3139 __ movq(rax, rbx);
3060 __ ret(0); 3140 __ ret(0);
3061 3141
3062 // Return the generated code. 3142 // Return the generated code.
3063 return GetCode(kind(), Code::NORMAL, name); 3143 return GetCode(kind(), Code::NORMAL, name);
3064 } 3144 }
3065 3145
3066 3146
3067 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( 3147 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC(
3068 MapHandleList* receiver_maps, 3148 TypeHandleList* types,
3069 CodeHandleList* handlers, 3149 CodeHandleList* handlers,
3070 Handle<Name> name, 3150 Handle<Name> name,
3071 Code::StubType type, 3151 Code::StubType type,
3072 IcCheckType check) { 3152 IcCheckType check) {
3073 Label miss; 3153 Label miss;
3074 3154
3075 if (check == PROPERTY) { 3155 if (check == PROPERTY) {
3076 GenerateNameCheck(name, this->name(), &miss); 3156 GenerateNameCheck(name, this->name(), &miss);
3077 } 3157 }
3078 3158
3079 __ JumpIfSmi(receiver(), &miss); 3159 Label number_case;
3160 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss;
3161 __ JumpIfSmi(receiver(), smi_target);
3162
3080 Register map_reg = scratch1(); 3163 Register map_reg = scratch1();
3081 __ movq(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); 3164 __ movq(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset));
3082 int receiver_count = receiver_maps->length(); 3165 int receiver_count = types->length();
3083 int number_of_handled_maps = 0; 3166 int number_of_handled_maps = 0;
3084 for (int current = 0; current < receiver_count; ++current) { 3167 for (int current = 0; current < receiver_count; ++current) {
3085 Handle<Map> map = receiver_maps->at(current); 3168 Handle<Type> type = types->at(current);
3169 Handle<Map> map = IC::TypeToMap(*type, isolate());
3086 if (!map->is_deprecated()) { 3170 if (!map->is_deprecated()) {
3087 number_of_handled_maps++; 3171 number_of_handled_maps++;
3088 // Check map and tail call if there's a match 3172 // Check map and tail call if there's a match
3089 __ Cmp(map_reg, receiver_maps->at(current)); 3173 __ Cmp(map_reg, map);
3174 if (type->Is(Type::Number())) {
3175 ASSERT(!number_case.is_unused());
3176 __ bind(&number_case);
3177 }
3090 __ j(equal, handlers->at(current), RelocInfo::CODE_TARGET); 3178 __ j(equal, handlers->at(current), RelocInfo::CODE_TARGET);
3091 } 3179 }
3092 } 3180 }
3093 ASSERT(number_of_handled_maps > 0); 3181 ASSERT(number_of_handled_maps > 0);
3094 3182
3095 __ bind(&miss); 3183 __ bind(&miss);
3096 TailCallBuiltin(masm(), MissBuiltin(kind())); 3184 TailCallBuiltin(masm(), MissBuiltin(kind()));
3097 3185
3098 // Return the generated code. 3186 // Return the generated code.
3099 InlineCacheState state = 3187 InlineCacheState state =
3100 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; 3188 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC;
3101 return GetICCode(kind(), type, name, state); 3189 return GetICCode(kind(), type, name, state);
3102 } 3190 }
3103 3191
3104 3192
3105 #undef __ 3193 #undef __
3106 #define __ ACCESS_MASM(masm) 3194 #define __ ACCESS_MASM(masm)
3107 3195
3108 3196
3109 void KeyedLoadStubCompiler::GenerateLoadDictionaryElement( 3197 void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
3110 MacroAssembler* masm) { 3198 MacroAssembler* masm) {
3111 // ----------- S t a t e ------------- 3199 // ----------- S t a t e -------------
3112 // -- rax : key 3200 // -- rax : key
3113 // -- rdx : receiver 3201 // -- rdx : receiver
3114 // -- rsp[0] : return address 3202 // -- rsp[0] : return address
3115 // ----------------------------------- 3203 // -----------------------------------
3116 Label slow, miss_force_generic; 3204 Label slow, miss;
3117 3205
3118 // This stub is meant to be tail-jumped to, the receiver must already 3206 // This stub is meant to be tail-jumped to, the receiver must already
3119 // have been verified by the caller to not be a smi. 3207 // have been verified by the caller to not be a smi.
3120 3208
3121 __ JumpIfNotSmi(rax, &miss_force_generic); 3209 __ JumpIfNotSmi(rax, &miss);
3122 __ SmiToInteger32(rbx, rax); 3210 __ SmiToInteger32(rbx, rax);
3123 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); 3211 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
3124 3212
3125 // Check whether the elements is a number dictionary. 3213 // Check whether the elements is a number dictionary.
3126 // rdx: receiver 3214 // rdx: receiver
3127 // rax: key 3215 // rax: key
3128 // rbx: key as untagged int32 3216 // rbx: key as untagged int32
3129 // rcx: elements 3217 // rcx: elements
3130 __ LoadFromNumberDictionary(&slow, rcx, rax, rbx, r9, rdi, rax); 3218 __ LoadFromNumberDictionary(&slow, rcx, rax, rbx, r9, rdi, rax);
3131 __ ret(0); 3219 __ ret(0);
3132 3220
3133 __ bind(&slow); 3221 __ bind(&slow);
3134 // ----------- S t a t e ------------- 3222 // ----------- S t a t e -------------
3135 // -- rax : key 3223 // -- rax : key
3136 // -- rdx : receiver 3224 // -- rdx : receiver
3137 // -- rsp[0] : return address 3225 // -- rsp[0] : return address
3138 // ----------------------------------- 3226 // -----------------------------------
3139 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow); 3227 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
3140 3228
3141 __ bind(&miss_force_generic); 3229 __ bind(&miss);
3142 // ----------- S t a t e ------------- 3230 // ----------- S t a t e -------------
3143 // -- rax : key 3231 // -- rax : key
3144 // -- rdx : receiver 3232 // -- rdx : receiver
3145 // -- rsp[0] : return address 3233 // -- rsp[0] : return address
3146 // ----------------------------------- 3234 // -----------------------------------
3147 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); 3235 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
3148 } 3236 }
3149 3237
3150 3238
3151 #undef __ 3239 #undef __
3152 3240
3153 } } // namespace v8::internal 3241 } } // namespace v8::internal
3154 3242
3155 #endif // V8_TARGET_ARCH_X64 3243 #endif // V8_TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698