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

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

Issue 151163005: A64: Synchronize with r16356. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 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/x64/macro-assembler-x64.cc ('k') | test/cctest/cctest.gyp » ('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 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 396 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 // These arguments are set by CheckPrototypes and GenerateFastApiCall. 407 // These arguments are set by CheckPrototypes and GenerateFastApiCall.
408 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { 408 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
409 // ----------- S t a t e ------------- 409 // ----------- S t a t e -------------
410 // -- rsp[0] : return address 410 // -- rsp[0] : return address
411 // -- rsp[8] : last argument in the internal frame of the caller 411 // -- rsp[8] : last argument in the internal frame of the caller
412 // ----------------------------------- 412 // -----------------------------------
413 __ movq(scratch, StackOperandForReturnAddress(0)); 413 __ movq(scratch, StackOperandForReturnAddress(0));
414 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); 414 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
415 __ movq(StackOperandForReturnAddress(0), scratch); 415 __ movq(StackOperandForReturnAddress(0), scratch);
416 __ Move(scratch, Smi::FromInt(0)); 416 __ Move(scratch, Smi::FromInt(0));
417 for (int i = 1; i <= kFastApiCallArguments; i++) { 417 StackArgumentsAccessor args(rsp, kFastApiCallArguments,
418 __ movq(Operand(rsp, i * kPointerSize), scratch); 418 ARGUMENTS_DONT_CONTAIN_RECEIVER);
419 for (int i = 0; i < kFastApiCallArguments; i++) {
420 __ movq(args.GetArgumentOperand(i), scratch);
419 } 421 }
420 } 422 }
421 423
422 424
423 // Undoes the effects of ReserveSpaceForFastApiCall. 425 // Undoes the effects of ReserveSpaceForFastApiCall.
424 static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { 426 static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
425 // ----------- S t a t e ------------- 427 // ----------- S t a t e -------------
426 // -- rsp[0] : return address. 428 // -- rsp[0] : return address.
427 // -- rsp[8] : last fast api call extra argument. 429 // -- rsp[8] : last fast api call extra argument.
428 // -- ... 430 // -- ...
(...skipping 28 matching lines...) Expand all
457 // -- rsp[56] : last argument 459 // -- rsp[56] : last argument
458 // -- ... 460 // -- ...
459 // -- rsp[(argc + 6) * 8] : first argument 461 // -- rsp[(argc + 6) * 8] : first argument
460 // -- rsp[(argc + 7) * 8] : receiver 462 // -- rsp[(argc + 7) * 8] : receiver
461 // ----------------------------------- 463 // -----------------------------------
462 // Get the function and setup the context. 464 // Get the function and setup the context.
463 Handle<JSFunction> function = optimization.constant_function(); 465 Handle<JSFunction> function = optimization.constant_function();
464 __ LoadHeapObject(rdi, function); 466 __ LoadHeapObject(rdi, function);
465 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); 467 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
466 468
469 int api_call_argc = argc + kFastApiCallArguments;
470 StackArgumentsAccessor args(rsp, api_call_argc);
471
467 // Pass the additional arguments. 472 // Pass the additional arguments.
468 __ movq(Operand(rsp, 2 * kPointerSize), rdi); 473 __ movq(args.GetArgumentOperand(api_call_argc - 1), rdi);
469 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 474 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
470 Handle<Object> call_data(api_call_info->data(), masm->isolate()); 475 Handle<Object> call_data(api_call_info->data(), masm->isolate());
471 if (masm->isolate()->heap()->InNewSpace(*call_data)) { 476 if (masm->isolate()->heap()->InNewSpace(*call_data)) {
472 __ Move(rcx, api_call_info); 477 __ Move(rcx, api_call_info);
473 __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset)); 478 __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset));
474 __ movq(Operand(rsp, 3 * kPointerSize), rbx); 479 __ movq(args.GetArgumentOperand(api_call_argc - 2), rbx);
475 } else { 480 } else {
476 __ Move(Operand(rsp, 3 * kPointerSize), call_data); 481 __ Move(args.GetArgumentOperand(api_call_argc - 2), call_data);
477 } 482 }
478 __ movq(kScratchRegister, 483 __ movq(kScratchRegister,
479 ExternalReference::isolate_address(masm->isolate())); 484 ExternalReference::isolate_address(masm->isolate()));
480 __ movq(Operand(rsp, 4 * kPointerSize), kScratchRegister); 485 __ movq(args.GetArgumentOperand(api_call_argc - 3), kScratchRegister);
481 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); 486 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
482 __ movq(Operand(rsp, 5 * kPointerSize), kScratchRegister); 487 __ movq(args.GetArgumentOperand(api_call_argc - 4), kScratchRegister);
483 __ movq(Operand(rsp, 6 * kPointerSize), kScratchRegister); 488 __ movq(args.GetArgumentOperand(api_call_argc - 5), kScratchRegister);
484 489
485 // Prepare arguments. 490 // Prepare arguments.
486 STATIC_ASSERT(kFastApiCallArguments == 6); 491 STATIC_ASSERT(kFastApiCallArguments == 6);
487 __ lea(rbx, Operand(rsp, kFastApiCallArguments * kPointerSize)); 492 __ lea(rbx, Operand(rsp, kFastApiCallArguments * kPointerSize));
488 493
489 // Function address is a foreign pointer outside V8's heap. 494 // Function address is a foreign pointer outside V8's heap.
490 Address function_address = v8::ToCData<Address>(api_call_info->callback()); 495 Address function_address = v8::ToCData<Address>(api_call_info->callback());
491 bool returns_handle = 496 // TODO(dcarney): fix signatures using returns_handle
492 !CallbackTable::ReturnsVoid(masm->isolate(), function_address); 497 const bool returns_handle = false;
493 498
494 #if defined(__MINGW64__) 499 #if defined(__MINGW64__)
495 Register arguments_arg = rcx; 500 Register arguments_arg = rcx;
496 Register callback_arg = rdx; 501 Register callback_arg = rdx;
497 #elif defined(_WIN64) 502 #elif defined(_WIN64)
498 // Win64 uses first register--rcx--for returned value. 503 // Win64 uses first register--rcx--for returned value.
499 Register arguments_arg = returns_handle ? rdx : rcx; 504 Register arguments_arg = returns_handle ? rdx : rcx;
500 Register callback_arg = returns_handle ? r8 : rdx; 505 Register callback_arg = returns_handle ? r8 : rdx;
501 #else 506 #else
502 Register arguments_arg = rdi; 507 Register arguments_arg = rdi;
503 Register callback_arg = rsi; 508 Register callback_arg = rsi;
504 #endif 509 #endif
505 510
506 // Allocate the v8::Arguments structure in the arguments' space since 511 // Allocate the v8::Arguments structure in the arguments' space since
507 // it's not controlled by GC. 512 // it's not controlled by GC.
508 const int kApiStackSpace = 4; 513 const int kApiStackSpace = 4;
509 514
510 __ PrepareCallApiFunction(kApiStackSpace, returns_handle); 515 __ PrepareCallApiFunction(kApiStackSpace, returns_handle);
511 516
512 __ movq(StackSpaceOperand(0), rbx); // v8::Arguments::implicit_args_. 517 __ movq(StackSpaceOperand(0), rbx); // v8::Arguments::implicit_args_.
513 __ addq(rbx, Immediate(argc * kPointerSize)); 518 __ addq(rbx, Immediate(argc * kPointerSize));
514 __ movq(StackSpaceOperand(1), rbx); // v8::Arguments::values_. 519 __ movq(StackSpaceOperand(1), rbx); // v8::Arguments::values_.
515 __ Set(StackSpaceOperand(2), argc); // v8::Arguments::length_. 520 __ Set(StackSpaceOperand(2), argc); // v8::Arguments::length_.
516 // v8::Arguments::is_construct_call_. 521 // v8::Arguments::is_construct_call_.
517 __ Set(StackSpaceOperand(3), 0); 522 __ Set(StackSpaceOperand(3), 0);
518 523
519 // v8::InvocationCallback's argument. 524 // v8::InvocationCallback's argument.
520 __ lea(arguments_arg, StackSpaceOperand(0)); 525 __ lea(arguments_arg, StackSpaceOperand(0));
521 526
522 Address thunk_address = returns_handle 527 Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback);
523 ? FUNCTION_ADDR(&InvokeInvocationCallback)
524 : FUNCTION_ADDR(&InvokeFunctionCallback);
525 528
526 __ CallApiFunctionAndReturn(function_address, 529 __ CallApiFunctionAndReturn(function_address,
527 thunk_address, 530 thunk_address,
528 callback_arg, 531 callback_arg,
529 argc + kFastApiCallArguments + 1, 532 api_call_argc + 1,
530 returns_handle, 533 returns_handle,
531 kFastApiCallArguments + 1); 534 kFastApiCallArguments + 1);
532 } 535 }
533 536
534 537
535 class CallInterceptorCompiler BASE_EMBEDDED { 538 class CallInterceptorCompiler BASE_EMBEDDED {
536 public: 539 public:
537 CallInterceptorCompiler(StubCompiler* stub_compiler, 540 CallInterceptorCompiler(StubCompiler* stub_compiler,
538 const ParameterCount& arguments, 541 const ParameterCount& arguments,
539 Register name, 542 Register name,
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after
1068 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) 1071 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
1069 && !scratch2.is(scratch1)); 1072 && !scratch2.is(scratch1));
1070 1073
1071 // Keep track of the current object in register reg. On the first 1074 // Keep track of the current object in register reg. On the first
1072 // iteration, reg is an alias for object_reg, on later iterations, 1075 // iteration, reg is an alias for object_reg, on later iterations,
1073 // it is an alias for holder_reg. 1076 // it is an alias for holder_reg.
1074 Register reg = object_reg; 1077 Register reg = object_reg;
1075 int depth = 0; 1078 int depth = 0;
1076 1079
1077 if (save_at_depth == depth) { 1080 if (save_at_depth == depth) {
1078 __ movq(Operand(rsp, kPointerSize), object_reg); 1081 __ movq(Operand(rsp, kPCOnStackSize), object_reg);
1079 } 1082 }
1080 1083
1081 // Check the maps in the prototype chain. 1084 // Check the maps in the prototype chain.
1082 // Traverse the prototype chain from the object and do map checks. 1085 // Traverse the prototype chain from the object and do map checks.
1083 Handle<JSObject> current = object; 1086 Handle<JSObject> current = object;
1084 while (!current.is_identical_to(holder)) { 1087 while (!current.is_identical_to(holder)) {
1085 ++depth; 1088 ++depth;
1086 1089
1087 // Only global objects and objects that do not require access 1090 // Only global objects and objects that do not require access
1088 // checks are allowed in stubs. 1091 // checks are allowed in stubs.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1128 // The prototype is in new space; we cannot store a reference to it 1131 // The prototype is in new space; we cannot store a reference to it
1129 // in the code. Load it from the map. 1132 // in the code. Load it from the map.
1130 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 1133 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
1131 } else { 1134 } else {
1132 // The prototype is in old space; load it directly. 1135 // The prototype is in old space; load it directly.
1133 __ Move(reg, prototype); 1136 __ Move(reg, prototype);
1134 } 1137 }
1135 } 1138 }
1136 1139
1137 if (save_at_depth == depth) { 1140 if (save_at_depth == depth) {
1138 __ movq(Operand(rsp, kPointerSize), reg); 1141 __ movq(Operand(rsp, kPCOnStackSize), reg);
1139 } 1142 }
1140 1143
1141 // Go to the next object in the prototype chain. 1144 // Go to the next object in the prototype chain.
1142 current = prototype; 1145 current = prototype;
1143 } 1146 }
1144 ASSERT(current.is_identical_to(holder)); 1147 ASSERT(current.is_identical_to(holder));
1145 1148
1146 // Log the check depth. 1149 // Log the check depth.
1147 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); 1150 LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
1148 1151
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
1297 } 1300 }
1298 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); 1301 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
1299 __ push(kScratchRegister); // return value 1302 __ push(kScratchRegister); // return value
1300 __ push(kScratchRegister); // return value default 1303 __ push(kScratchRegister); // return value default
1301 __ PushAddress(ExternalReference::isolate_address(isolate())); 1304 __ PushAddress(ExternalReference::isolate_address(isolate()));
1302 __ push(name()); // name 1305 __ push(name()); // name
1303 // Save a pointer to where we pushed the arguments pointer. This will be 1306 // Save a pointer to where we pushed the arguments pointer. This will be
1304 // passed as the const ExecutableAccessorInfo& to the C++ callback. 1307 // passed as the const ExecutableAccessorInfo& to the C++ callback.
1305 1308
1306 Address getter_address = v8::ToCData<Address>(callback->getter()); 1309 Address getter_address = v8::ToCData<Address>(callback->getter());
1307 bool returns_handle = 1310 // TODO(dcarney): fix signatures using returns_handle
1308 !CallbackTable::ReturnsVoid(isolate(), getter_address); 1311 const bool returns_handle = false;
1309 1312
1310 #if defined(__MINGW64__) 1313 #if defined(__MINGW64__)
1311 Register getter_arg = r8; 1314 Register getter_arg = r8;
1312 Register accessor_info_arg = rdx; 1315 Register accessor_info_arg = rdx;
1313 Register name_arg = rcx; 1316 Register name_arg = rcx;
1314 #elif defined(_WIN64) 1317 #elif defined(_WIN64)
1315 // Win64 uses first register--rcx--for returned value. 1318 // Win64 uses first register--rcx--for returned value.
1316 Register getter_arg = returns_handle ? r9 : r8; 1319 Register getter_arg = returns_handle ? r9 : r8;
1317 Register accessor_info_arg = returns_handle ? r8 : rdx; 1320 Register accessor_info_arg = returns_handle ? r8 : rdx;
1318 Register name_arg = returns_handle ? rdx : rcx; 1321 Register name_arg = returns_handle ? rdx : rcx;
(...skipping 17 matching lines...) Expand all
1336 STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6); 1339 STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6);
1337 __ lea(rax, Operand(name_arg, 6 * kPointerSize)); 1340 __ lea(rax, Operand(name_arg, 6 * kPointerSize));
1338 1341
1339 // v8::AccessorInfo::args_. 1342 // v8::AccessorInfo::args_.
1340 __ movq(StackSpaceOperand(0), rax); 1343 __ movq(StackSpaceOperand(0), rax);
1341 1344
1342 // The context register (rsi) has been saved in PrepareCallApiFunction and 1345 // The context register (rsi) has been saved in PrepareCallApiFunction and
1343 // could be used to pass arguments. 1346 // could be used to pass arguments.
1344 __ lea(accessor_info_arg, StackSpaceOperand(0)); 1347 __ lea(accessor_info_arg, StackSpaceOperand(0));
1345 1348
1346 Address thunk_address = returns_handle 1349 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback);
1347 ? FUNCTION_ADDR(&InvokeAccessorGetter)
1348 : FUNCTION_ADDR(&InvokeAccessorGetterCallback);
1349 1350
1350 __ CallApiFunctionAndReturn(getter_address, 1351 __ CallApiFunctionAndReturn(getter_address,
1351 thunk_address, 1352 thunk_address,
1352 getter_arg, 1353 getter_arg,
1353 kStackSpace, 1354 kStackSpace,
1354 returns_handle, 1355 returns_handle,
1355 5); 1356 5);
1356 } 1357 }
1357 1358
1358 1359
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
1463 } 1464 }
1464 } 1465 }
1465 1466
1466 1467
1467 void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, 1468 void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
1468 Handle<JSObject> holder, 1469 Handle<JSObject> holder,
1469 Handle<Name> name, 1470 Handle<Name> name,
1470 Label* miss) { 1471 Label* miss) {
1471 ASSERT(holder->IsGlobalObject()); 1472 ASSERT(holder->IsGlobalObject());
1472 1473
1473 // Get the number of arguments. 1474 StackArgumentsAccessor args(rsp, arguments());
1474 const int argc = arguments().immediate(); 1475 __ movq(rdx, args.GetReceiverOperand());
1475
1476 // Get the receiver from the stack.
1477 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1478 1476
1479 1477
1480 // Check that the maps haven't changed. 1478 // Check that the maps haven't changed.
1481 __ JumpIfSmi(rdx, miss); 1479 __ JumpIfSmi(rdx, miss);
1482 CheckPrototypes(object, rdx, holder, rbx, rax, rdi, name, miss); 1480 CheckPrototypes(object, rdx, holder, rbx, rax, rdi, name, miss);
1483 } 1481 }
1484 1482
1485 1483
1486 void CallStubCompiler::GenerateLoadFunctionFromCell( 1484 void CallStubCompiler::GenerateLoadFunctionFromCell(
1487 Handle<Cell> cell, 1485 Handle<Cell> cell,
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1531 // rsp[8] : argument argc 1529 // rsp[8] : argument argc
1532 // rsp[16] : argument argc - 1 1530 // rsp[16] : argument argc - 1
1533 // ... 1531 // ...
1534 // rsp[argc * 8] : argument 1 1532 // rsp[argc * 8] : argument 1
1535 // rsp[(argc + 1) * 8] : argument 0 = receiver 1533 // rsp[(argc + 1) * 8] : argument 0 = receiver
1536 // ----------------------------------- 1534 // -----------------------------------
1537 Label miss; 1535 Label miss;
1538 1536
1539 GenerateNameCheck(name, &miss); 1537 GenerateNameCheck(name, &miss);
1540 1538
1541 // Get the receiver from the stack. 1539 StackArgumentsAccessor args(rsp, arguments());
1542 const int argc = arguments().immediate(); 1540 __ movq(rdx, args.GetReceiverOperand());
1543 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1544 1541
1545 // Check that the receiver isn't a smi. 1542 // Check that the receiver isn't a smi.
1546 __ JumpIfSmi(rdx, &miss); 1543 __ JumpIfSmi(rdx, &miss);
1547 1544
1548 // Do the right check and compute the holder register. 1545 // Do the right check and compute the holder register.
1549 Register reg = CheckPrototypes(object, rdx, holder, rbx, rax, rdi, 1546 Register reg = CheckPrototypes(object, rdx, holder, rbx, rax, rdi,
1550 name, &miss); 1547 name, &miss);
1551 1548
1552 GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder), 1549 GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder),
1553 index.translate(holder), Representation::Tagged()); 1550 index.translate(holder), Representation::Tagged());
1554 1551
1555 // Check that the function really is a function. 1552 // Check that the function really is a function.
1556 __ JumpIfSmi(rdi, &miss); 1553 __ JumpIfSmi(rdi, &miss);
1557 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx); 1554 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx);
1558 __ j(not_equal, &miss); 1555 __ j(not_equal, &miss);
1559 1556
1560 // Patch the receiver on the stack with the global proxy if 1557 // Patch the receiver on the stack with the global proxy if
1561 // necessary. 1558 // necessary.
1562 if (object->IsGlobalObject()) { 1559 if (object->IsGlobalObject()) {
1563 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); 1560 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
1564 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); 1561 __ movq(args.GetReceiverOperand(), rdx);
1565 } 1562 }
1566 1563
1567 // Invoke the function. 1564 // Invoke the function.
1568 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 1565 CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
1569 ? CALL_AS_FUNCTION 1566 ? CALL_AS_FUNCTION
1570 : CALL_AS_METHOD; 1567 : CALL_AS_METHOD;
1571 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, 1568 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
1572 NullCallWrapper(), call_kind); 1569 NullCallWrapper(), call_kind);
1573 1570
1574 // Handle call cache miss. 1571 // Handle call cache miss.
1575 __ bind(&miss); 1572 __ bind(&miss);
1576 GenerateMissBranch(); 1573 GenerateMissBranch();
1577 1574
1578 // Return the generated code. 1575 // Return the generated code.
1579 return GetCode(Code::FIELD, name); 1576 return GetCode(Code::FIELD, name);
1580 } 1577 }
1581 1578
1582 1579
1583 Handle<Code> CallStubCompiler::CompileArrayCodeCall( 1580 Handle<Code> CallStubCompiler::CompileArrayCodeCall(
1584 Handle<Object> object, 1581 Handle<Object> object,
1585 Handle<JSObject> holder, 1582 Handle<JSObject> holder,
1586 Handle<Cell> cell, 1583 Handle<Cell> cell,
1587 Handle<JSFunction> function, 1584 Handle<JSFunction> function,
1588 Handle<String> name, 1585 Handle<String> name,
1589 Code::StubType type) { 1586 Code::StubType type) {
1590 Label miss; 1587 Label miss;
1591 1588
1592 // Check that function is still array 1589 // Check that function is still array
1593 const int argc = arguments().immediate(); 1590 const int argc = arguments().immediate();
1591 StackArgumentsAccessor args(rsp, argc);
1594 GenerateNameCheck(name, &miss); 1592 GenerateNameCheck(name, &miss);
1595 1593
1596 if (cell.is_null()) { 1594 if (cell.is_null()) {
1597 // Get the receiver from the stack. 1595 __ movq(rdx, args.GetReceiverOperand());
1598 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1599 1596
1600 // Check that the receiver isn't a smi. 1597 // Check that the receiver isn't a smi.
1601 __ JumpIfSmi(rdx, &miss); 1598 __ JumpIfSmi(rdx, &miss);
1602 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, 1599 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
1603 name, &miss); 1600 name, &miss);
1604 } else { 1601 } else {
1605 ASSERT(cell->value() == *function); 1602 ASSERT(cell->value() == *function);
1606 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 1603 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
1607 &miss); 1604 &miss);
1608 GenerateLoadFunctionFromCell(cell, function, &miss); 1605 GenerateLoadFunctionFromCell(cell, function, &miss);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1640 // -- ... 1637 // -- ...
1641 // -- rsp[(argc + 1) * 8] : receiver 1638 // -- rsp[(argc + 1) * 8] : receiver
1642 // ----------------------------------- 1639 // -----------------------------------
1643 1640
1644 // If object is not an array, bail out to regular call. 1641 // If object is not an array, bail out to regular call.
1645 if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); 1642 if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null();
1646 1643
1647 Label miss; 1644 Label miss;
1648 GenerateNameCheck(name, &miss); 1645 GenerateNameCheck(name, &miss);
1649 1646
1650 // Get the receiver from the stack.
1651 const int argc = arguments().immediate(); 1647 const int argc = arguments().immediate();
1652 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 1648 StackArgumentsAccessor args(rsp, argc);
1649 __ movq(rdx, args.GetReceiverOperand());
1653 1650
1654 // Check that the receiver isn't a smi. 1651 // Check that the receiver isn't a smi.
1655 __ JumpIfSmi(rdx, &miss); 1652 __ JumpIfSmi(rdx, &miss);
1656 1653
1657 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, 1654 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
1658 name, &miss); 1655 name, &miss);
1659 1656
1660 if (argc == 0) { 1657 if (argc == 0) {
1661 // Noop, return the length. 1658 // Noop, return the length.
1662 __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset)); 1659 __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset));
(...skipping 18 matching lines...) Expand all
1681 __ addl(rax, Immediate(argc)); 1678 __ addl(rax, Immediate(argc));
1682 1679
1683 // Get the elements' length into rcx. 1680 // Get the elements' length into rcx.
1684 __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); 1681 __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
1685 1682
1686 // Check if we could survive without allocation. 1683 // Check if we could survive without allocation.
1687 __ cmpl(rax, rcx); 1684 __ cmpl(rax, rcx);
1688 __ j(greater, &attempt_to_grow_elements); 1685 __ j(greater, &attempt_to_grow_elements);
1689 1686
1690 // Check if value is a smi. 1687 // Check if value is a smi.
1691 __ movq(rcx, Operand(rsp, argc * kPointerSize)); 1688 __ movq(rcx, args.GetArgumentOperand(1));
1692 __ JumpIfNotSmi(rcx, &with_write_barrier); 1689 __ JumpIfNotSmi(rcx, &with_write_barrier);
1693 1690
1694 // Save new length. 1691 // Save new length.
1695 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax); 1692 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
1696 1693
1697 // Store the value. 1694 // Store the value.
1698 __ movq(FieldOperand(rdi, 1695 __ movq(FieldOperand(rdi,
1699 rax, 1696 rax,
1700 times_pointer_size, 1697 times_pointer_size,
1701 FixedArray::kHeaderSize - argc * kPointerSize), 1698 FixedArray::kHeaderSize - argc * kPointerSize),
(...skipping 14 matching lines...) Expand all
1716 STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue); 1713 STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue);
1717 __ addl(rax, Immediate(argc)); 1714 __ addl(rax, Immediate(argc));
1718 1715
1719 // Get the elements' length into rcx. 1716 // Get the elements' length into rcx.
1720 __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); 1717 __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
1721 1718
1722 // Check if we could survive without allocation. 1719 // Check if we could survive without allocation.
1723 __ cmpl(rax, rcx); 1720 __ cmpl(rax, rcx);
1724 __ j(greater, &call_builtin); 1721 __ j(greater, &call_builtin);
1725 1722
1726 __ movq(rcx, Operand(rsp, argc * kPointerSize)); 1723 __ movq(rcx, args.GetArgumentOperand(1));
1727 __ StoreNumberToDoubleElements( 1724 __ StoreNumberToDoubleElements(
1728 rcx, rdi, rax, xmm0, &call_builtin, argc * kDoubleSize); 1725 rcx, rdi, rax, xmm0, &call_builtin, argc * kDoubleSize);
1729 1726
1730 // Save new length. 1727 // Save new length.
1731 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax); 1728 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
1732 __ Integer32ToSmi(rax, rax); // Return new length as smi. 1729 __ Integer32ToSmi(rax, rax); // Return new length as smi.
1733 __ ret((argc + 1) * kPointerSize); 1730 __ ret((argc + 1) * kPointerSize);
1734 1731
1735 __ bind(&with_write_barrier); 1732 __ bind(&with_write_barrier);
1736 1733
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1793 OMIT_SMI_CHECK); 1790 OMIT_SMI_CHECK);
1794 1791
1795 __ Integer32ToSmi(rax, rax); // Return new length as smi. 1792 __ Integer32ToSmi(rax, rax); // Return new length as smi.
1796 __ ret((argc + 1) * kPointerSize); 1793 __ ret((argc + 1) * kPointerSize);
1797 1794
1798 __ bind(&attempt_to_grow_elements); 1795 __ bind(&attempt_to_grow_elements);
1799 if (!FLAG_inline_new) { 1796 if (!FLAG_inline_new) {
1800 __ jmp(&call_builtin); 1797 __ jmp(&call_builtin);
1801 } 1798 }
1802 1799
1803 __ movq(rbx, Operand(rsp, argc * kPointerSize)); 1800 __ movq(rbx, args.GetArgumentOperand(1));
1804 // Growing elements that are SMI-only requires special handling in case 1801 // Growing elements that are SMI-only requires special handling in case
1805 // the new element is non-Smi. For now, delegate to the builtin. 1802 // the new element is non-Smi. For now, delegate to the builtin.
1806 Label no_fast_elements_check; 1803 Label no_fast_elements_check;
1807 __ JumpIfSmi(rbx, &no_fast_elements_check); 1804 __ JumpIfSmi(rbx, &no_fast_elements_check);
1808 __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); 1805 __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset));
1809 __ CheckFastObjectElements(rcx, &call_builtin, Label::kFar); 1806 __ CheckFastObjectElements(rcx, &call_builtin, Label::kFar);
1810 __ bind(&no_fast_elements_check); 1807 __ bind(&no_fast_elements_check);
1811 1808
1812 ExternalReference new_space_allocation_top = 1809 ExternalReference new_space_allocation_top =
1813 ExternalReference::new_space_allocation_top_address(isolate()); 1810 ExternalReference::new_space_allocation_top_address(isolate());
(...skipping 28 matching lines...) Expand all
1842 } 1839 }
1843 1840
1844 // We know the elements array is in new space so we don't need the 1841 // We know the elements array is in new space so we don't need the
1845 // remembered set, but we just pushed a value onto it so we may have to 1842 // remembered set, but we just pushed a value onto it so we may have to
1846 // tell the incremental marker to rescan the object that we just grew. We 1843 // tell the incremental marker to rescan the object that we just grew. We
1847 // don't need to worry about the holes because they are in old space and 1844 // don't need to worry about the holes because they are in old space and
1848 // already marked black. 1845 // already marked black.
1849 __ RecordWrite(rdi, rdx, rbx, kDontSaveFPRegs, OMIT_REMEMBERED_SET); 1846 __ RecordWrite(rdi, rdx, rbx, kDontSaveFPRegs, OMIT_REMEMBERED_SET);
1850 1847
1851 // Restore receiver to rdx as finish sequence assumes it's here. 1848 // Restore receiver to rdx as finish sequence assumes it's here.
1852 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 1849 __ movq(rdx, args.GetReceiverOperand());
1853 1850
1854 // Increment element's and array's sizes. 1851 // Increment element's and array's sizes.
1855 __ SmiAddConstant(FieldOperand(rdi, FixedArray::kLengthOffset), 1852 __ SmiAddConstant(FieldOperand(rdi, FixedArray::kLengthOffset),
1856 Smi::FromInt(kAllocationDelta)); 1853 Smi::FromInt(kAllocationDelta));
1857 1854
1858 // Make new length a smi before returning it. 1855 // Make new length a smi before returning it.
1859 __ Integer32ToSmi(rax, rax); 1856 __ Integer32ToSmi(rax, rax);
1860 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax); 1857 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax);
1861 1858
1862 __ ret((argc + 1) * kPointerSize); 1859 __ ret((argc + 1) * kPointerSize);
(...skipping 28 matching lines...) Expand all
1891 // -- ... 1888 // -- ...
1892 // -- rsp[(argc + 1) * 8] : receiver 1889 // -- rsp[(argc + 1) * 8] : receiver
1893 // ----------------------------------- 1890 // -----------------------------------
1894 1891
1895 // If object is not an array, bail out to regular call. 1892 // If object is not an array, bail out to regular call.
1896 if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); 1893 if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null();
1897 1894
1898 Label miss, return_undefined, call_builtin; 1895 Label miss, return_undefined, call_builtin;
1899 GenerateNameCheck(name, &miss); 1896 GenerateNameCheck(name, &miss);
1900 1897
1901 // Get the receiver from the stack.
1902 const int argc = arguments().immediate(); 1898 const int argc = arguments().immediate();
1903 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 1899 StackArgumentsAccessor args(rsp, argc);
1900 __ movq(rdx, args.GetReceiverOperand());
1904 1901
1905 // Check that the receiver isn't a smi. 1902 // Check that the receiver isn't a smi.
1906 __ JumpIfSmi(rdx, &miss); 1903 __ JumpIfSmi(rdx, &miss);
1907 1904
1908 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, 1905 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
1909 name, &miss); 1906 name, &miss);
1910 1907
1911 // Get the elements array of the object. 1908 // Get the elements array of the object.
1912 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); 1909 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset));
1913 1910
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1971 // -- rsp[0] : return address 1968 // -- rsp[0] : return address
1972 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) 1969 // -- rsp[(argc - n) * 8] : arg[n] (zero-based)
1973 // -- ... 1970 // -- ...
1974 // -- rsp[(argc + 1) * 8] : receiver 1971 // -- rsp[(argc + 1) * 8] : receiver
1975 // ----------------------------------- 1972 // -----------------------------------
1976 1973
1977 // If object is not a string, bail out to regular call. 1974 // If object is not a string, bail out to regular call.
1978 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); 1975 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
1979 1976
1980 const int argc = arguments().immediate(); 1977 const int argc = arguments().immediate();
1978 StackArgumentsAccessor args(rsp, argc);
1981 1979
1982 Label miss; 1980 Label miss;
1983 Label name_miss; 1981 Label name_miss;
1984 Label index_out_of_range; 1982 Label index_out_of_range;
1985 Label* index_out_of_range_label = &index_out_of_range; 1983 Label* index_out_of_range_label = &index_out_of_range;
1986 if (kind_ == Code::CALL_IC && 1984 if (kind_ == Code::CALL_IC &&
1987 (CallICBase::StringStubState::decode(extra_state_) == 1985 (CallICBase::StringStubState::decode(extra_state_) ==
1988 DEFAULT_STRING_STUB)) { 1986 DEFAULT_STRING_STUB)) {
1989 index_out_of_range_label = &miss; 1987 index_out_of_range_label = &miss;
1990 } 1988 }
1991 GenerateNameCheck(name, &name_miss); 1989 GenerateNameCheck(name, &name_miss);
1992 1990
1993 // Check that the maps starting from the prototype haven't changed. 1991 // Check that the maps starting from the prototype haven't changed.
1994 GenerateDirectLoadGlobalFunctionPrototype(masm(), 1992 GenerateDirectLoadGlobalFunctionPrototype(masm(),
1995 Context::STRING_FUNCTION_INDEX, 1993 Context::STRING_FUNCTION_INDEX,
1996 rax, 1994 rax,
1997 &miss); 1995 &miss);
1998 ASSERT(!object.is_identical_to(holder)); 1996 ASSERT(!object.is_identical_to(holder));
1999 CheckPrototypes( 1997 CheckPrototypes(
2000 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), 1998 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))),
2001 rax, holder, rbx, rdx, rdi, name, &miss); 1999 rax, holder, rbx, rdx, rdi, name, &miss);
2002 2000
2003 Register receiver = rbx; 2001 Register receiver = rbx;
2004 Register index = rdi; 2002 Register index = rdi;
2005 Register result = rax; 2003 Register result = rax;
2006 __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize)); 2004 __ movq(receiver, args.GetReceiverOperand());
2007 if (argc > 0) { 2005 if (argc > 0) {
2008 __ movq(index, Operand(rsp, (argc - 0) * kPointerSize)); 2006 __ movq(index, args.GetArgumentOperand(1));
2009 } else { 2007 } else {
2010 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); 2008 __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
2011 } 2009 }
2012 2010
2013 StringCharCodeAtGenerator generator(receiver, 2011 StringCharCodeAtGenerator generator(receiver,
2014 index, 2012 index,
2015 result, 2013 result,
2016 &miss, // When not a string. 2014 &miss, // When not a string.
2017 &miss, // When not a number. 2015 &miss, // When not a number.
2018 index_out_of_range_label, 2016 index_out_of_range_label,
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
2052 // -- rsp[0] : return address 2050 // -- rsp[0] : return address
2053 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) 2051 // -- rsp[(argc - n) * 8] : arg[n] (zero-based)
2054 // -- ... 2052 // -- ...
2055 // -- rsp[(argc + 1) * 8] : receiver 2053 // -- rsp[(argc + 1) * 8] : receiver
2056 // ----------------------------------- 2054 // -----------------------------------
2057 2055
2058 // If object is not a string, bail out to regular call. 2056 // If object is not a string, bail out to regular call.
2059 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); 2057 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
2060 2058
2061 const int argc = arguments().immediate(); 2059 const int argc = arguments().immediate();
2060 StackArgumentsAccessor args(rsp, argc);
2061
2062 Label miss; 2062 Label miss;
2063 Label name_miss; 2063 Label name_miss;
2064 Label index_out_of_range; 2064 Label index_out_of_range;
2065 Label* index_out_of_range_label = &index_out_of_range; 2065 Label* index_out_of_range_label = &index_out_of_range;
2066 if (kind_ == Code::CALL_IC && 2066 if (kind_ == Code::CALL_IC &&
2067 (CallICBase::StringStubState::decode(extra_state_) == 2067 (CallICBase::StringStubState::decode(extra_state_) ==
2068 DEFAULT_STRING_STUB)) { 2068 DEFAULT_STRING_STUB)) {
2069 index_out_of_range_label = &miss; 2069 index_out_of_range_label = &miss;
2070 } 2070 }
2071 GenerateNameCheck(name, &name_miss); 2071 GenerateNameCheck(name, &name_miss);
2072 2072
2073 // Check that the maps starting from the prototype haven't changed. 2073 // Check that the maps starting from the prototype haven't changed.
2074 GenerateDirectLoadGlobalFunctionPrototype(masm(), 2074 GenerateDirectLoadGlobalFunctionPrototype(masm(),
2075 Context::STRING_FUNCTION_INDEX, 2075 Context::STRING_FUNCTION_INDEX,
2076 rax, 2076 rax,
2077 &miss); 2077 &miss);
2078 ASSERT(!object.is_identical_to(holder)); 2078 ASSERT(!object.is_identical_to(holder));
2079 CheckPrototypes( 2079 CheckPrototypes(
2080 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), 2080 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))),
2081 rax, holder, rbx, rdx, rdi, name, &miss); 2081 rax, holder, rbx, rdx, rdi, name, &miss);
2082 2082
2083 Register receiver = rax; 2083 Register receiver = rax;
2084 Register index = rdi; 2084 Register index = rdi;
2085 Register scratch = rdx; 2085 Register scratch = rdx;
2086 Register result = rax; 2086 Register result = rax;
2087 __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize)); 2087 __ movq(receiver, args.GetReceiverOperand());
2088 if (argc > 0) { 2088 if (argc > 0) {
2089 __ movq(index, Operand(rsp, (argc - 0) * kPointerSize)); 2089 __ movq(index, args.GetArgumentOperand(1));
2090 } else { 2090 } else {
2091 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); 2091 __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
2092 } 2092 }
2093 2093
2094 StringCharAtGenerator generator(receiver, 2094 StringCharAtGenerator generator(receiver,
2095 index, 2095 index,
2096 scratch, 2096 scratch,
2097 result, 2097 result,
2098 &miss, // When not a string. 2098 &miss, // When not a string.
2099 &miss, // When not a number. 2099 &miss, // When not a number.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
2132 // -- rcx : function name 2132 // -- rcx : function name
2133 // -- rsp[0] : return address 2133 // -- rsp[0] : return address
2134 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) 2134 // -- rsp[(argc - n) * 8] : arg[n] (zero-based)
2135 // -- ... 2135 // -- ...
2136 // -- rsp[(argc + 1) * 8] : receiver 2136 // -- rsp[(argc + 1) * 8] : receiver
2137 // ----------------------------------- 2137 // -----------------------------------
2138 2138
2139 // If the object is not a JSObject or we got an unexpected number of 2139 // If the object is not a JSObject or we got an unexpected number of
2140 // arguments, bail out to the regular call. 2140 // arguments, bail out to the regular call.
2141 const int argc = arguments().immediate(); 2141 const int argc = arguments().immediate();
2142 StackArgumentsAccessor args(rsp, argc);
2142 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); 2143 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
2143 2144
2144 Label miss; 2145 Label miss;
2145 GenerateNameCheck(name, &miss); 2146 GenerateNameCheck(name, &miss);
2146 2147
2147 if (cell.is_null()) { 2148 if (cell.is_null()) {
2148 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); 2149 __ movq(rdx, args.GetArgumentOperand(argc - 1));
2149 __ JumpIfSmi(rdx, &miss); 2150 __ JumpIfSmi(rdx, &miss);
2150 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, 2151 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
2151 name, &miss); 2152 name, &miss);
2152 } else { 2153 } else {
2153 ASSERT(cell->value() == *function); 2154 ASSERT(cell->value() == *function);
2154 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 2155 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
2155 &miss); 2156 &miss);
2156 GenerateLoadFunctionFromCell(cell, function, &miss); 2157 GenerateLoadFunctionFromCell(cell, function, &miss);
2157 } 2158 }
2158 2159
2159 // Load the char code argument. 2160 // Load the char code argument.
2160 Register code = rbx; 2161 Register code = rbx;
2161 __ movq(code, Operand(rsp, 1 * kPointerSize)); 2162 __ movq(code, args.GetArgumentOperand(argc));
2162 2163
2163 // Check the code is a smi. 2164 // Check the code is a smi.
2164 Label slow; 2165 Label slow;
2165 __ JumpIfNotSmi(code, &slow); 2166 __ JumpIfNotSmi(code, &slow);
2166 2167
2167 // Convert the smi code to uint16. 2168 // Convert the smi code to uint16.
2168 __ SmiAndConstant(code, code, Smi::FromInt(0xffff)); 2169 __ SmiAndConstant(code, code, Smi::FromInt(0xffff));
2169 2170
2170 StringCharFromCodeGenerator generator(code, rax); 2171 StringCharFromCodeGenerator generator(code, rax);
2171 generator.GenerateFast(masm()); 2172 generator.GenerateFast(masm());
(...skipping 21 matching lines...) Expand all
2193 } 2194 }
2194 2195
2195 2196
2196 Handle<Code> CallStubCompiler::CompileMathFloorCall( 2197 Handle<Code> CallStubCompiler::CompileMathFloorCall(
2197 Handle<Object> object, 2198 Handle<Object> object,
2198 Handle<JSObject> holder, 2199 Handle<JSObject> holder,
2199 Handle<Cell> cell, 2200 Handle<Cell> cell,
2200 Handle<JSFunction> function, 2201 Handle<JSFunction> function,
2201 Handle<String> name, 2202 Handle<String> name,
2202 Code::StubType type) { 2203 Code::StubType type) {
2203 // TODO(872): implement this. 2204 // ----------- S t a t e -------------
2204 return Handle<Code>::null(); 2205 // -- rcx : name
2206 // -- rsp[0] : return address
2207 // -- rsp[(argc - n) * 4] : arg[n] (zero-based)
2208 // -- ...
2209 // -- rsp[(argc + 1) * 4] : receiver
2210 // -----------------------------------
2211
2212 if (!CpuFeatures::IsSupported(SSE2)) {
2213 return Handle<Code>::null();
2214 }
2215
2216 CpuFeatureScope use_sse2(masm(), SSE2);
2217
2218 const int argc = arguments().immediate();
2219
2220 // If the object is not a JSObject or we got an unexpected number of
2221 // arguments, bail out to the regular call.
2222 if (!object->IsJSObject() || argc != 1) {
2223 return Handle<Code>::null();
2224 }
2225
2226 Label miss;
2227 GenerateNameCheck(name, &miss);
2228
2229 if (cell.is_null()) {
2230 __ movq(rdx, Operand(rsp, 2 * kPointerSize));
2231
2232 STATIC_ASSERT(kSmiTag == 0);
2233 __ JumpIfSmi(rdx, &miss);
2234
2235 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
2236 name, &miss);
2237 } else {
2238 ASSERT(cell->value() == *function);
2239 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
2240 &miss);
2241 GenerateLoadFunctionFromCell(cell, function, &miss);
2242 }
2243
2244 // Load the (only) argument into rax.
2245 __ movq(rax, Operand(rsp, 1 * kPointerSize));
2246
2247 // Check if the argument is a smi.
2248 Label smi;
2249 STATIC_ASSERT(kSmiTag == 0);
2250 __ JumpIfSmi(rax, &smi);
2251
2252 // Check if the argument is a heap number and load its value into xmm0.
2253 Label slow;
2254 __ CheckMap(rax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
2255 __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
2256
2257 // Check if the argument is strictly positive. Note this also discards NaN.
2258 __ xorpd(xmm1, xmm1);
2259 __ ucomisd(xmm0, xmm1);
2260 __ j(below_equal, &slow);
2261
2262 // Do a truncating conversion.
2263 __ cvttsd2si(rax, xmm0);
2264
2265 // Checks for 0x80000000 which signals a failed conversion.
2266 Label conversion_failure;
2267 __ cmpl(rax, Immediate(0x80000000));
2268 __ j(equal, &conversion_failure);
2269
2270 // Smi tag and return.
2271 __ Integer32ToSmi(rax, rax);
2272 __ bind(&smi);
2273 __ ret(2 * kPointerSize);
2274
2275 // Check if the argument is < 2^kMantissaBits.
2276 Label already_round;
2277 __ bind(&conversion_failure);
2278 int64_t kTwoMantissaBits= V8_INT64_C(0x4330000000000000);
2279 __ movq(rbx, kTwoMantissaBits, RelocInfo::NONE64);
2280 __ movq(xmm1, rbx);
2281 __ ucomisd(xmm0, xmm1);
2282 __ j(above_equal, &already_round);
2283
2284 // Save a copy of the argument.
2285 __ movaps(xmm2, xmm0);
2286
2287 // Compute (argument + 2^kMantissaBits) - 2^kMantissaBits.
2288 __ addsd(xmm0, xmm1);
2289 __ subsd(xmm0, xmm1);
2290
2291 // Compare the argument and the tentative result to get the right mask:
2292 // if xmm2 < xmm0:
2293 // xmm2 = 1...1
2294 // else:
2295 // xmm2 = 0...0
2296 __ cmpltsd(xmm2, xmm0);
2297
2298 // Subtract 1 if the argument was less than the tentative result.
2299 int64_t kOne = V8_INT64_C(0x3ff0000000000000);
2300 __ movq(rbx, kOne, RelocInfo::NONE64);
2301 __ movq(xmm1, rbx);
2302 __ andpd(xmm1, xmm2);
2303 __ subsd(xmm0, xmm1);
2304
2305 // Return a new heap number.
2306 __ AllocateHeapNumber(rax, rbx, &slow);
2307 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0);
2308 __ ret(2 * kPointerSize);
2309
2310 // Return the argument (when it's an already round heap number).
2311 __ bind(&already_round);
2312 __ movq(rax, Operand(rsp, 1 * kPointerSize));
2313 __ ret(2 * kPointerSize);
2314
2315 // Tail call the full function. We do not have to patch the receiver
2316 // because the function makes no use of it.
2317 __ bind(&slow);
2318 ParameterCount expected(function);
2319 __ InvokeFunction(function, expected, arguments(),
2320 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
2321
2322 __ bind(&miss);
2323 // rcx: function name.
2324 GenerateMissBranch();
2325
2326 // Return the generated code.
2327 return GetCode(type, name);
2205 } 2328 }
2206 2329
2207 2330
2208 Handle<Code> CallStubCompiler::CompileMathAbsCall( 2331 Handle<Code> CallStubCompiler::CompileMathAbsCall(
2209 Handle<Object> object, 2332 Handle<Object> object,
2210 Handle<JSObject> holder, 2333 Handle<JSObject> holder,
2211 Handle<Cell> cell, 2334 Handle<Cell> cell,
2212 Handle<JSFunction> function, 2335 Handle<JSFunction> function,
2213 Handle<String> name, 2336 Handle<String> name,
2214 Code::StubType type) { 2337 Code::StubType type) {
2215 // ----------- S t a t e ------------- 2338 // ----------- S t a t e -------------
2216 // -- rcx : function name 2339 // -- rcx : function name
2217 // -- rsp[0] : return address 2340 // -- rsp[0] : return address
2218 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) 2341 // -- rsp[(argc - n) * 8] : arg[n] (zero-based)
2219 // -- ... 2342 // -- ...
2220 // -- rsp[(argc + 1) * 8] : receiver 2343 // -- rsp[(argc + 1) * 8] : receiver
2221 // ----------------------------------- 2344 // -----------------------------------
2222 2345
2223 // If the object is not a JSObject or we got an unexpected number of 2346 // If the object is not a JSObject or we got an unexpected number of
2224 // arguments, bail out to the regular call. 2347 // arguments, bail out to the regular call.
2225 const int argc = arguments().immediate(); 2348 const int argc = arguments().immediate();
2349 StackArgumentsAccessor args(rsp, argc);
2226 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); 2350 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
2227 2351
2228 Label miss; 2352 Label miss;
2229 GenerateNameCheck(name, &miss); 2353 GenerateNameCheck(name, &miss);
2230 2354
2231 if (cell.is_null()) { 2355 if (cell.is_null()) {
2232 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); 2356 __ movq(rdx, args.GetArgumentOperand(argc - 1));
2233 __ JumpIfSmi(rdx, &miss); 2357 __ JumpIfSmi(rdx, &miss);
2234 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, 2358 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
2235 name, &miss); 2359 name, &miss);
2236 } else { 2360 } else {
2237 ASSERT(cell->value() == *function); 2361 ASSERT(cell->value() == *function);
2238 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 2362 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
2239 &miss); 2363 &miss);
2240 GenerateLoadFunctionFromCell(cell, function, &miss); 2364 GenerateLoadFunctionFromCell(cell, function, &miss);
2241 } 2365 }
2242 // Load the (only) argument into rax. 2366 // Load the (only) argument into rax.
2243 __ movq(rax, Operand(rsp, 1 * kPointerSize)); 2367 __ movq(rax, args.GetArgumentOperand(argc));
2244 2368
2245 // Check if the argument is a smi. 2369 // Check if the argument is a smi.
2246 Label not_smi; 2370 Label not_smi;
2247 STATIC_ASSERT(kSmiTag == 0); 2371 STATIC_ASSERT(kSmiTag == 0);
2248 __ JumpIfNotSmi(rax, &not_smi); 2372 __ JumpIfNotSmi(rax, &not_smi);
2249 2373
2250 // Branchless abs implementation, refer to below: 2374 // Branchless abs implementation, refer to below:
2251 // http://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs 2375 // http://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs
2252 // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0 2376 // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0
2253 // otherwise. 2377 // otherwise.
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
2323 if (object->IsGlobalObject()) return Handle<Code>::null(); 2447 if (object->IsGlobalObject()) return Handle<Code>::null();
2324 if (!cell.is_null()) return Handle<Code>::null(); 2448 if (!cell.is_null()) return Handle<Code>::null();
2325 if (!object->IsJSObject()) return Handle<Code>::null(); 2449 if (!object->IsJSObject()) return Handle<Code>::null();
2326 int depth = optimization.GetPrototypeDepthOfExpectedType( 2450 int depth = optimization.GetPrototypeDepthOfExpectedType(
2327 Handle<JSObject>::cast(object), holder); 2451 Handle<JSObject>::cast(object), holder);
2328 if (depth == kInvalidProtoDepth) return Handle<Code>::null(); 2452 if (depth == kInvalidProtoDepth) return Handle<Code>::null();
2329 2453
2330 Label miss, miss_before_stack_reserved; 2454 Label miss, miss_before_stack_reserved;
2331 GenerateNameCheck(name, &miss_before_stack_reserved); 2455 GenerateNameCheck(name, &miss_before_stack_reserved);
2332 2456
2333 // Get the receiver from the stack.
2334 const int argc = arguments().immediate(); 2457 const int argc = arguments().immediate();
2335 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 2458 StackArgumentsAccessor args(rsp, argc);
2459 __ movq(rdx, args.GetReceiverOperand());
2336 2460
2337 // Check that the receiver isn't a smi. 2461 // Check that the receiver isn't a smi.
2338 __ JumpIfSmi(rdx, &miss_before_stack_reserved); 2462 __ JumpIfSmi(rdx, &miss_before_stack_reserved);
2339 2463
2340 Counters* counters = isolate()->counters(); 2464 Counters* counters = isolate()->counters();
2341 __ IncrementCounter(counters->call_const(), 1); 2465 __ IncrementCounter(counters->call_const(), 1);
2342 __ IncrementCounter(counters->call_const_fast_api(), 1); 2466 __ IncrementCounter(counters->call_const_fast_api(), 1);
2343 2467
2344 // Allocate space for v8::Arguments implicit values. Must be initialized 2468 // Allocate space for v8::Arguments implicit values. Must be initialized
2345 // before calling any runtime function. 2469 // before calling any runtime function.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2377 // rsp[0] : return address 2501 // rsp[0] : return address
2378 // rsp[8] : argument argc 2502 // rsp[8] : argument argc
2379 // rsp[16] : argument argc - 1 2503 // rsp[16] : argument argc - 1
2380 // ... 2504 // ...
2381 // rsp[argc * 8] : argument 1 2505 // rsp[argc * 8] : argument 1
2382 // rsp[(argc + 1) * 8] : argument 0 = receiver 2506 // rsp[(argc + 1) * 8] : argument 0 = receiver
2383 // ----------------------------------- 2507 // -----------------------------------
2384 Label miss; 2508 Label miss;
2385 GenerateNameCheck(name, &miss); 2509 GenerateNameCheck(name, &miss);
2386 2510
2387 // Get the receiver from the stack. 2511 StackArgumentsAccessor args(rsp, arguments());
2388 const int argc = arguments().immediate(); 2512 __ movq(rdx, args.GetReceiverOperand());
2389 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
2390 2513
2391 // Check that the receiver isn't a smi. 2514 // Check that the receiver isn't a smi.
2392 if (check != NUMBER_CHECK) { 2515 if (check != NUMBER_CHECK) {
2393 __ JumpIfSmi(rdx, &miss); 2516 __ JumpIfSmi(rdx, &miss);
2394 } 2517 }
2395 2518
2396 // Make sure that it's okay not to patch the on stack receiver 2519 // Make sure that it's okay not to patch the on stack receiver
2397 // unless we're doing a receiver map check. 2520 // unless we're doing a receiver map check.
2398 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); 2521 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
2399 2522
2400 Counters* counters = isolate()->counters(); 2523 Counters* counters = isolate()->counters();
2401 switch (check) { 2524 switch (check) {
2402 case RECEIVER_MAP_CHECK: 2525 case RECEIVER_MAP_CHECK:
2403 __ IncrementCounter(counters->call_const(), 1); 2526 __ IncrementCounter(counters->call_const(), 1);
2404 2527
2405 // Check that the maps haven't changed. 2528 // Check that the maps haven't changed.
2406 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, 2529 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax,
2407 rdi, name, &miss); 2530 rdi, name, &miss);
2408 2531
2409 // Patch the receiver on the stack with the global proxy if 2532 // Patch the receiver on the stack with the global proxy if
2410 // necessary. 2533 // necessary.
2411 if (object->IsGlobalObject()) { 2534 if (object->IsGlobalObject()) {
2412 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); 2535 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
2413 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); 2536 __ movq(args.GetReceiverOperand(), rdx);
2414 } 2537 }
2415 break; 2538 break;
2416 2539
2417 case STRING_CHECK: 2540 case STRING_CHECK:
2418 // Check that the object is a string. 2541 // Check that the object is a string.
2419 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax); 2542 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax);
2420 __ j(above_equal, &miss); 2543 __ j(above_equal, &miss);
2421 // Check that the maps starting from the prototype haven't changed. 2544 // Check that the maps starting from the prototype haven't changed.
2422 GenerateDirectLoadGlobalFunctionPrototype( 2545 GenerateDirectLoadGlobalFunctionPrototype(
2423 masm(), Context::STRING_FUNCTION_INDEX, rax, &miss); 2546 masm(), Context::STRING_FUNCTION_INDEX, rax, &miss);
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
2523 // rsp[0] : return address 2646 // rsp[0] : return address
2524 // rsp[8] : argument argc 2647 // rsp[8] : argument argc
2525 // rsp[16] : argument argc - 1 2648 // rsp[16] : argument argc - 1
2526 // ... 2649 // ...
2527 // rsp[argc * 8] : argument 1 2650 // rsp[argc * 8] : argument 1
2528 // rsp[(argc + 1) * 8] : argument 0 = receiver 2651 // rsp[(argc + 1) * 8] : argument 0 = receiver
2529 // ----------------------------------- 2652 // -----------------------------------
2530 Label miss; 2653 Label miss;
2531 GenerateNameCheck(name, &miss); 2654 GenerateNameCheck(name, &miss);
2532 2655
2533 // Get the number of arguments.
2534 const int argc = arguments().immediate();
2535 2656
2536 LookupResult lookup(isolate()); 2657 LookupResult lookup(isolate());
2537 LookupPostInterceptor(holder, name, &lookup); 2658 LookupPostInterceptor(holder, name, &lookup);
2538 2659
2539 // Get the receiver from the stack. 2660 // Get the receiver from the stack.
2540 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 2661 StackArgumentsAccessor args(rsp, arguments());
2662 __ movq(rdx, args.GetReceiverOperand());
2541 2663
2542 CallInterceptorCompiler compiler(this, arguments(), rcx, extra_state_); 2664 CallInterceptorCompiler compiler(this, arguments(), rcx, extra_state_);
2543 compiler.Compile(masm(), object, holder, name, &lookup, rdx, rbx, rdi, rax, 2665 compiler.Compile(masm(), object, holder, name, &lookup, rdx, rbx, rdi, rax,
2544 &miss); 2666 &miss);
2545 2667
2546 // Restore receiver. 2668 // Restore receiver.
2547 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 2669 __ movq(rdx, args.GetReceiverOperand());
2548 2670
2549 // Check that the function really is a function. 2671 // Check that the function really is a function.
2550 __ JumpIfSmi(rax, &miss); 2672 __ JumpIfSmi(rax, &miss);
2551 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); 2673 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
2552 __ j(not_equal, &miss); 2674 __ j(not_equal, &miss);
2553 2675
2554 // Patch the receiver on the stack with the global proxy if 2676 // Patch the receiver on the stack with the global proxy if
2555 // necessary. 2677 // necessary.
2556 if (object->IsGlobalObject()) { 2678 if (object->IsGlobalObject()) {
2557 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); 2679 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
2558 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); 2680 __ movq(args.GetReceiverOperand(), rdx);
2559 } 2681 }
2560 2682
2561 // Invoke the function. 2683 // Invoke the function.
2562 __ movq(rdi, rax); 2684 __ movq(rdi, rax);
2563 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2685 CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
2564 ? CALL_AS_FUNCTION 2686 ? CALL_AS_FUNCTION
2565 : CALL_AS_METHOD; 2687 : CALL_AS_METHOD;
2566 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, 2688 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
2567 NullCallWrapper(), call_kind); 2689 NullCallWrapper(), call_kind);
2568 2690
(...skipping 26 matching lines...) Expand all
2595 Handle<Code> code = CompileCustomCall( 2717 Handle<Code> code = CompileCustomCall(
2596 object, holder, cell, function, Handle<String>::cast(name), 2718 object, holder, cell, function, Handle<String>::cast(name),
2597 Code::NORMAL); 2719 Code::NORMAL);
2598 // A null handle means bail out to the regular compiler code below. 2720 // A null handle means bail out to the regular compiler code below.
2599 if (!code.is_null()) return code; 2721 if (!code.is_null()) return code;
2600 } 2722 }
2601 2723
2602 Label miss; 2724 Label miss;
2603 GenerateNameCheck(name, &miss); 2725 GenerateNameCheck(name, &miss);
2604 2726
2605 // Get the number of arguments. 2727 StackArgumentsAccessor args(rsp, arguments());
2606 const int argc = arguments().immediate();
2607 GenerateGlobalReceiverCheck(object, holder, name, &miss); 2728 GenerateGlobalReceiverCheck(object, holder, name, &miss);
2608 GenerateLoadFunctionFromCell(cell, function, &miss); 2729 GenerateLoadFunctionFromCell(cell, function, &miss);
2609 2730
2610 // Patch the receiver on the stack with the global proxy. 2731 // Patch the receiver on the stack with the global proxy.
2611 if (object->IsGlobalObject()) { 2732 if (object->IsGlobalObject()) {
2612 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); 2733 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
2613 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); 2734 __ movq(args.GetReceiverOperand(), rdx);
2614 } 2735 }
2615 2736
2616 // Set up the context (function already in rdi). 2737 // Set up the context (function already in rdi).
2617 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); 2738 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
2618 2739
2619 // Jump to the cached code (tail call). 2740 // Jump to the cached code (tail call).
2620 Counters* counters = isolate()->counters(); 2741 Counters* counters = isolate()->counters();
2621 __ IncrementCounter(counters->call_global_inline(), 1); 2742 __ IncrementCounter(counters->call_global_inline(), 1);
2622 ParameterCount expected(function->shared()->formal_parameter_count()); 2743 ParameterCount expected(function->shared()->formal_parameter_count());
2623 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2744 CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
(...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after
3035 // ----------------------------------- 3156 // -----------------------------------
3036 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric); 3157 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_MissForceGeneric);
3037 } 3158 }
3038 3159
3039 3160
3040 #undef __ 3161 #undef __
3041 3162
3042 } } // namespace v8::internal 3163 } } // namespace v8::internal
3043 3164
3044 #endif // V8_TARGET_ARCH_X64 3165 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/macro-assembler-x64.cc ('k') | test/cctest/cctest.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698