| OLD | NEW |
| 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 19 matching lines...) Expand all Loading... |
| 30 #if V8_TARGET_ARCH_X64 | 30 #if V8_TARGET_ARCH_X64 |
| 31 | 31 |
| 32 #include "ic-inl.h" | 32 #include "ic-inl.h" |
| 33 #include "codegen.h" | 33 #include "codegen.h" |
| 34 #include "stub-cache.h" | 34 #include "stub-cache.h" |
| 35 | 35 |
| 36 namespace v8 { | 36 namespace v8 { |
| 37 namespace internal { | 37 namespace internal { |
| 38 | 38 |
| 39 #define __ ACCESS_MASM(masm) | 39 #define __ ACCESS_MASM(masm) |
| 40 #define __k __ |
| 41 #define __a __ |
| 40 | 42 |
| 41 | 43 |
| 42 static void ProbeTable(Isolate* isolate, | 44 static void ProbeTable(Isolate* isolate, |
| 43 MacroAssembler* masm, | 45 MacroAssembler* masm, |
| 44 Code::Flags flags, | 46 Code::Flags flags, |
| 45 StubCache::Table table, | 47 StubCache::Table table, |
| 46 Register receiver, | 48 Register receiver, |
| 47 Register name, | 49 Register name, |
| 48 // The offset is scaled by 4, based on | 50 // The offset is scaled by 4, based on |
| 49 // kHeapObjectTagSize, which is two bits | 51 // kHeapObjectTagSize, which is two bits |
| 50 Register offset) { | 52 Register offset) { |
| 51 // We need to scale up the pointer by 2 because the offset is scaled by less | 53 // We need to scale up the pointer by 2 because the offset is scaled by less |
| 52 // than the pointer size. | 54 // than the pointer size. |
| 55 #ifndef V8_TARGET_ARCH_X32 |
| 53 ASSERT(kPointerSizeLog2 == kHeapObjectTagSize + 1); | 56 ASSERT(kPointerSizeLog2 == kHeapObjectTagSize + 1); |
| 54 ScaleFactor scale_factor = times_2; | 57 ScaleFactor scale_factor = times_2; |
| 58 #else |
| 59 ASSERT(kPointerSizeLog2 == kHeapObjectTagSize); |
| 60 ScaleFactor scale_factor = times_1; |
| 61 #endif |
| 55 | 62 |
| 56 ASSERT_EQ(3 * kPointerSize, sizeof(StubCache::Entry)); | 63 ASSERT_EQ(3 * kPointerSize, sizeof(StubCache::Entry)); |
| 57 // The offset register holds the entry offset times four (due to masking | 64 // The offset register holds the entry offset times four (due to masking |
| 58 // and shifting optimizations). | 65 // and shifting optimizations). |
| 59 ExternalReference key_offset(isolate->stub_cache()->key_reference(table)); | 66 ExternalReference key_offset(isolate->stub_cache()->key_reference(table)); |
| 60 ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); | 67 ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); |
| 61 Label miss; | 68 Label miss; |
| 62 | 69 |
| 63 // Multiply by 3 because there are 3 fields per entry (name, code, map). | 70 // Multiply by 3 because there are 3 fields per entry (name, code, map). |
| 64 __ lea(offset, Operand(offset, offset, times_2, 0)); | 71 __ lea(offset, Operand(offset, offset, times_2, 0)); |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 403 | 410 |
| 404 // Reserves space for the extra arguments to API function in the | 411 // Reserves space for the extra arguments to API function in the |
| 405 // caller's frame. | 412 // caller's frame. |
| 406 // | 413 // |
| 407 // These arguments are set by CheckPrototypes and GenerateFastApiCall. | 414 // These arguments are set by CheckPrototypes and GenerateFastApiCall. |
| 408 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { | 415 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { |
| 409 // ----------- S t a t e ------------- | 416 // ----------- S t a t e ------------- |
| 410 // -- rsp[0] : return address | 417 // -- rsp[0] : return address |
| 411 // -- rsp[8] : last argument in the internal frame of the caller | 418 // -- rsp[8] : last argument in the internal frame of the caller |
| 412 // ----------------------------------- | 419 // ----------------------------------- |
| 413 __ movq(scratch, Operand(rsp, 0)); | 420 __k movq(scratch, Operand(rsp, 0)); |
| 414 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); | 421 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 415 __ movq(Operand(rsp, 0), scratch); | 422 __k movq(Operand(rsp, 0), scratch); |
| 416 __ Move(scratch, Smi::FromInt(0)); | 423 __ Move(scratch, Smi::FromInt(0)); |
| 417 for (int i = 1; i <= kFastApiCallArguments; i++) { | 424 for (int i = 1; i <= kFastApiCallArguments; i++) { |
| 418 __ movq(Operand(rsp, i * kPointerSize), scratch); | 425 __a movq(Operand(rsp, i * kPointerSize), scratch); |
| 419 } | 426 } |
| 420 } | 427 } |
| 421 | 428 |
| 422 | 429 |
| 423 // Undoes the effects of ReserveSpaceForFastApiCall. | 430 // Undoes the effects of ReserveSpaceForFastApiCall. |
| 424 static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { | 431 static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { |
| 425 // ----------- S t a t e ------------- | 432 // ----------- S t a t e ------------- |
| 426 // -- rsp[0] : return address. | 433 // -- rsp[0] : return address. |
| 427 // -- rsp[8] : last fast api call extra argument. | 434 // -- rsp[8] : last fast api call extra argument. |
| 428 // -- ... | 435 // -- ... |
| 429 // -- rsp[kFastApiCallArguments * 8] : first fast api call extra | 436 // -- rsp[kFastApiCallArguments * 8] : first fast api call extra |
| 430 // argument. | 437 // argument. |
| 431 // -- rsp[kFastApiCallArguments * 8 + 8] : last argument in the internal | 438 // -- rsp[kFastApiCallArguments * 8 + 8] : last argument in the internal |
| 432 // frame. | 439 // frame. |
| 433 // ----------------------------------- | 440 // ----------------------------------- |
| 434 __ movq(scratch, Operand(rsp, 0)); | 441 __k movq(scratch, Operand(rsp, 0)); |
| 435 __ movq(Operand(rsp, kFastApiCallArguments * kPointerSize), scratch); | 442 __k movq(Operand(rsp, kFastApiCallArguments * kPointerSize), scratch); |
| 436 __ addq(rsp, Immediate(kPointerSize * kFastApiCallArguments)); | 443 __ addq(rsp, Immediate(kPointerSize * kFastApiCallArguments)); |
| 437 } | 444 } |
| 438 | 445 |
| 439 | 446 |
| 440 // Generates call to API function. | 447 // Generates call to API function. |
| 441 static void GenerateFastApiCall(MacroAssembler* masm, | 448 static void GenerateFastApiCall(MacroAssembler* masm, |
| 442 const CallOptimization& optimization, | 449 const CallOptimization& optimization, |
| 443 int argc) { | 450 int argc) { |
| 444 // ----------- S t a t e ------------- | 451 // ----------- S t a t e ------------- |
| 445 // -- rsp[0] : return address | 452 // -- rsp[0] : return address |
| (...skipping 11 matching lines...) Expand all Loading... |
| 457 // -- ... | 464 // -- ... |
| 458 // -- rsp[(argc + 6) * 8] : first argument | 465 // -- rsp[(argc + 6) * 8] : first argument |
| 459 // -- rsp[(argc + 7) * 8] : receiver | 466 // -- rsp[(argc + 7) * 8] : receiver |
| 460 // ----------------------------------- | 467 // ----------------------------------- |
| 461 // Get the function and setup the context. | 468 // Get the function and setup the context. |
| 462 Handle<JSFunction> function = optimization.constant_function(); | 469 Handle<JSFunction> function = optimization.constant_function(); |
| 463 __ LoadHeapObject(rdi, function); | 470 __ LoadHeapObject(rdi, function); |
| 464 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | 471 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
| 465 | 472 |
| 466 // Pass the additional arguments. | 473 // Pass the additional arguments. |
| 467 __ movq(Operand(rsp, 2 * kPointerSize), rdi); | 474 __a movq(Operand(rsp, 2 * kPointerSize), rdi); |
| 468 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); | 475 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); |
| 469 Handle<Object> call_data(api_call_info->data(), masm->isolate()); | 476 Handle<Object> call_data(api_call_info->data(), masm->isolate()); |
| 470 if (masm->isolate()->heap()->InNewSpace(*call_data)) { | 477 if (masm->isolate()->heap()->InNewSpace(*call_data)) { |
| 471 __ Move(rcx, api_call_info); | 478 __ Move(rcx, api_call_info); |
| 472 __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset)); | 479 __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset)); |
| 473 __ movq(Operand(rsp, 3 * kPointerSize), rbx); | 480 __a movq(Operand(rsp, 3 * kPointerSize), rbx); |
| 474 } else { | 481 } else { |
| 475 __ Move(Operand(rsp, 3 * kPointerSize), call_data); | 482 __a Move(Operand(rsp, 3 * kPointerSize), call_data); |
| 476 } | 483 } |
| 477 __ movq(kScratchRegister, | 484 __ movq(kScratchRegister, |
| 478 ExternalReference::isolate_address(masm->isolate())); | 485 ExternalReference::isolate_address(masm->isolate())); |
| 479 __ movq(Operand(rsp, 4 * kPointerSize), kScratchRegister); | 486 __a movq(Operand(rsp, 4 * kPointerSize), kScratchRegister); |
| 480 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); | 487 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); |
| 481 __ movq(Operand(rsp, 5 * kPointerSize), kScratchRegister); | 488 __a movq(Operand(rsp, 5 * kPointerSize), kScratchRegister); |
| 482 __ movq(Operand(rsp, 6 * kPointerSize), kScratchRegister); | 489 __a movq(Operand(rsp, 6 * kPointerSize), kScratchRegister); |
| 483 | 490 |
| 484 // Prepare arguments. | 491 // Prepare arguments. |
| 485 STATIC_ASSERT(kFastApiCallArguments == 6); | 492 STATIC_ASSERT(kFastApiCallArguments == 6); |
| 493 #ifndef V8_TARGET_ARCH_X32 |
| 486 __ lea(rbx, Operand(rsp, kFastApiCallArguments * kPointerSize)); | 494 __ lea(rbx, Operand(rsp, kFastApiCallArguments * kPointerSize)); |
| 495 #else |
| 496 __ leal(rbx, Operand(rsp, 1 * kHWRegSize + |
| 497 (kFastApiCallArguments - 1) * kPointerSize)); |
| 498 #endif |
| 487 | 499 |
| 488 // Function address is a foreign pointer outside V8's heap. | 500 // Function address is a foreign pointer outside V8's heap. |
| 489 Address function_address = v8::ToCData<Address>(api_call_info->callback()); | 501 Address function_address = v8::ToCData<Address>(api_call_info->callback()); |
| 490 bool returns_handle = | 502 bool returns_handle = |
| 491 !CallbackTable::ReturnsVoid(masm->isolate(), function_address); | 503 !CallbackTable::ReturnsVoid(masm->isolate(), function_address); |
| 492 | 504 |
| 493 #if defined(__MINGW64__) | 505 #if defined(__MINGW64__) |
| 494 Register arguments_arg = rcx; | 506 Register arguments_arg = rcx; |
| 495 Register callback_arg = rdx; | 507 Register callback_arg = rdx; |
| 496 #elif defined(_WIN64) | 508 #elif defined(_WIN64) |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 857 | 869 |
| 858 // Stub never generated for non-global objects that require access | 870 // Stub never generated for non-global objects that require access |
| 859 // checks. | 871 // checks. |
| 860 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 872 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 861 | 873 |
| 862 // Perform map transition for the receiver if necessary. | 874 // Perform map transition for the receiver if necessary. |
| 863 if (details.type() == FIELD && | 875 if (details.type() == FIELD && |
| 864 object->map()->unused_property_fields() == 0) { | 876 object->map()->unused_property_fields() == 0) { |
| 865 // The properties must be extended before we can store the value. | 877 // The properties must be extended before we can store the value. |
| 866 // We jump to a runtime call that extends the properties array. | 878 // We jump to a runtime call that extends the properties array. |
| 867 __ pop(scratch1); // Return address. | 879 __k pop(scratch1); // Return address. |
| 868 __ push(receiver_reg); | 880 __ push(receiver_reg); |
| 869 __ Push(transition); | 881 __ Push(transition); |
| 870 __ push(value_reg); | 882 __ push(value_reg); |
| 871 __ push(scratch1); | 883 __k push(scratch1); |
| 872 __ TailCallExternalReference( | 884 __ TailCallExternalReference( |
| 873 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), | 885 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |
| 874 masm->isolate()), | 886 masm->isolate()), |
| 875 3, | 887 3, |
| 876 1); | 888 1); |
| 877 return; | 889 return; |
| 878 } | 890 } |
| 879 | 891 |
| 880 // Update the map of the object. | 892 // Update the map of the object. |
| 881 __ Move(scratch1, transition); | 893 __ Move(scratch1, transition); |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1113 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 1125 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
| 1114 && !scratch2.is(scratch1)); | 1126 && !scratch2.is(scratch1)); |
| 1115 | 1127 |
| 1116 // Keep track of the current object in register reg. On the first | 1128 // Keep track of the current object in register reg. On the first |
| 1117 // iteration, reg is an alias for object_reg, on later iterations, | 1129 // iteration, reg is an alias for object_reg, on later iterations, |
| 1118 // it is an alias for holder_reg. | 1130 // it is an alias for holder_reg. |
| 1119 Register reg = object_reg; | 1131 Register reg = object_reg; |
| 1120 int depth = 0; | 1132 int depth = 0; |
| 1121 | 1133 |
| 1122 if (save_at_depth == depth) { | 1134 if (save_at_depth == depth) { |
| 1123 __ movq(Operand(rsp, kPointerSize), object_reg); | 1135 __a movq(Operand(rsp, 1 * kPointerSize), object_reg); |
| 1124 } | 1136 } |
| 1125 | 1137 |
| 1126 // Check the maps in the prototype chain. | 1138 // Check the maps in the prototype chain. |
| 1127 // Traverse the prototype chain from the object and do map checks. | 1139 // Traverse the prototype chain from the object and do map checks. |
| 1128 Handle<JSObject> current = object; | 1140 Handle<JSObject> current = object; |
| 1129 while (!current.is_identical_to(holder)) { | 1141 while (!current.is_identical_to(holder)) { |
| 1130 ++depth; | 1142 ++depth; |
| 1131 | 1143 |
| 1132 // Only global objects and objects that do not require access | 1144 // Only global objects and objects that do not require access |
| 1133 // checks are allowed in stubs. | 1145 // checks are allowed in stubs. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1173 // The prototype is in new space; we cannot store a reference to it | 1185 // The prototype is in new space; we cannot store a reference to it |
| 1174 // in the code. Load it from the map. | 1186 // in the code. Load it from the map. |
| 1175 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 1187 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 1176 } else { | 1188 } else { |
| 1177 // The prototype is in old space; load it directly. | 1189 // The prototype is in old space; load it directly. |
| 1178 __ Move(reg, prototype); | 1190 __ Move(reg, prototype); |
| 1179 } | 1191 } |
| 1180 } | 1192 } |
| 1181 | 1193 |
| 1182 if (save_at_depth == depth) { | 1194 if (save_at_depth == depth) { |
| 1183 __ movq(Operand(rsp, kPointerSize), reg); | 1195 __a movq(Operand(rsp, 1 * kPointerSize), reg); |
| 1184 } | 1196 } |
| 1185 | 1197 |
| 1186 // Go to the next object in the prototype chain. | 1198 // Go to the next object in the prototype chain. |
| 1187 current = prototype; | 1199 current = prototype; |
| 1188 } | 1200 } |
| 1189 ASSERT(current.is_identical_to(holder)); | 1201 ASSERT(current.is_identical_to(holder)); |
| 1190 | 1202 |
| 1191 // Log the check depth. | 1203 // Log the check depth. |
| 1192 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 1204 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
| 1193 | 1205 |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1310 GenerateTailCall(masm(), stub.GetCode(isolate())); | 1322 GenerateTailCall(masm(), stub.GetCode(isolate())); |
| 1311 } | 1323 } |
| 1312 } | 1324 } |
| 1313 | 1325 |
| 1314 | 1326 |
| 1315 void BaseLoadStubCompiler::GenerateLoadCallback( | 1327 void BaseLoadStubCompiler::GenerateLoadCallback( |
| 1316 Register reg, | 1328 Register reg, |
| 1317 Handle<ExecutableAccessorInfo> callback) { | 1329 Handle<ExecutableAccessorInfo> callback) { |
| 1318 // Insert additional parameters into the stack frame above return address. | 1330 // Insert additional parameters into the stack frame above return address. |
| 1319 ASSERT(!scratch4().is(reg)); | 1331 ASSERT(!scratch4().is(reg)); |
| 1320 __ pop(scratch4()); // Get return address to place it below. | 1332 __k pop(scratch4()); // Get return address to place it below. |
| 1321 | 1333 |
| 1322 __ push(receiver()); // receiver | 1334 __ push(receiver()); // receiver |
| 1323 __ push(reg); // holder | 1335 __ push(reg); // holder |
| 1324 if (heap()->InNewSpace(callback->data())) { | 1336 if (heap()->InNewSpace(callback->data())) { |
| 1325 __ Move(scratch1(), callback); | 1337 __ Move(scratch1(), callback); |
| 1326 __ push(FieldOperand(scratch1(), | 1338 __ push(FieldOperand(scratch1(), |
| 1327 ExecutableAccessorInfo::kDataOffset)); // data | 1339 ExecutableAccessorInfo::kDataOffset)); // data |
| 1328 } else { | 1340 } else { |
| 1329 __ Push(Handle<Object>(callback->data(), isolate())); | 1341 __ Push(Handle<Object>(callback->data(), isolate())); |
| 1330 } | 1342 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1350 Register accessor_info_arg = returns_handle ? r8 : rdx; | 1362 Register accessor_info_arg = returns_handle ? r8 : rdx; |
| 1351 Register name_arg = returns_handle ? rdx : rcx; | 1363 Register name_arg = returns_handle ? rdx : rcx; |
| 1352 #else | 1364 #else |
| 1353 Register getter_arg = rdx; | 1365 Register getter_arg = rdx; |
| 1354 Register accessor_info_arg = rsi; | 1366 Register accessor_info_arg = rsi; |
| 1355 Register name_arg = rdi; | 1367 Register name_arg = rdi; |
| 1356 #endif | 1368 #endif |
| 1357 | 1369 |
| 1358 ASSERT(!name_arg.is(scratch4())); | 1370 ASSERT(!name_arg.is(scratch4())); |
| 1359 __ movq(name_arg, rsp); | 1371 __ movq(name_arg, rsp); |
| 1360 __ push(scratch4()); // Restore return address. | 1372 __k push(scratch4()); // Restore return address. |
| 1361 | 1373 |
| 1362 // v8::Arguments::values_ and handler for name. | 1374 // v8::Arguments::values_ and handler for name. |
| 1363 const int kStackSpace = PropertyCallbackArguments::kArgsLength + 1; | 1375 const int kStackSpace = PropertyCallbackArguments::kArgsLength + 1; |
| 1364 | 1376 |
| 1365 // Allocate v8::AccessorInfo in non-GCed stack space. | 1377 // Allocate v8::AccessorInfo in non-GCed stack space. |
| 1366 const int kArgStackSpace = 1; | 1378 const int kArgStackSpace = 1; |
| 1367 | 1379 |
| 1368 __ PrepareCallApiFunction(kArgStackSpace, returns_handle); | 1380 __ PrepareCallApiFunction(kArgStackSpace, returns_handle); |
| 1369 STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6); | 1381 STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6); |
| 1370 __ lea(rax, Operand(name_arg, 6 * kPointerSize)); | 1382 __ lea(rax, Operand(name_arg, 6 * kPointerSize)); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1470 __ pop(receiver()); | 1482 __ pop(receiver()); |
| 1471 } | 1483 } |
| 1472 | 1484 |
| 1473 // Leave the internal frame. | 1485 // Leave the internal frame. |
| 1474 } | 1486 } |
| 1475 | 1487 |
| 1476 GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup); | 1488 GenerateLoadPostInterceptor(holder_reg, interceptor_holder, name, lookup); |
| 1477 } else { // !compile_followup_inline | 1489 } else { // !compile_followup_inline |
| 1478 // Call the runtime system to load the interceptor. | 1490 // Call the runtime system to load the interceptor. |
| 1479 // Check that the maps haven't changed. | 1491 // Check that the maps haven't changed. |
| 1480 __ pop(scratch2()); // save old return address | 1492 __k pop(scratch2()); // save old return address |
| 1481 PushInterceptorArguments(masm(), receiver(), holder_reg, | 1493 PushInterceptorArguments(masm(), receiver(), holder_reg, |
| 1482 this->name(), interceptor_holder); | 1494 this->name(), interceptor_holder); |
| 1483 __ push(scratch2()); // restore old return address | 1495 __k push(scratch2()); // restore old return address |
| 1484 | 1496 |
| 1485 ExternalReference ref = ExternalReference( | 1497 ExternalReference ref = ExternalReference( |
| 1486 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), isolate()); | 1498 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), isolate()); |
| 1487 __ TailCallExternalReference(ref, 6, 1); | 1499 __ TailCallExternalReference(ref, 6, 1); |
| 1488 } | 1500 } |
| 1489 } | 1501 } |
| 1490 | 1502 |
| 1491 | 1503 |
| 1492 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { | 1504 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { |
| 1493 if (kind_ == Code::KEYED_CALL_IC) { | 1505 if (kind_ == Code::KEYED_CALL_IC) { |
| 1494 __ Cmp(rcx, name); | 1506 __ Cmp(rcx, name); |
| 1495 __ j(not_equal, miss); | 1507 __ j(not_equal, miss); |
| 1496 } | 1508 } |
| 1497 } | 1509 } |
| 1498 | 1510 |
| 1499 | 1511 |
| 1500 void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, | 1512 void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, |
| 1501 Handle<JSObject> holder, | 1513 Handle<JSObject> holder, |
| 1502 Handle<Name> name, | 1514 Handle<Name> name, |
| 1503 Label* miss) { | 1515 Label* miss) { |
| 1504 ASSERT(holder->IsGlobalObject()); | 1516 ASSERT(holder->IsGlobalObject()); |
| 1505 | 1517 |
| 1506 // Get the number of arguments. | 1518 // Get the number of arguments. |
| 1507 const int argc = arguments().immediate(); | 1519 const int argc = arguments().immediate(); |
| 1508 | 1520 |
| 1509 // Get the receiver from the stack. | 1521 // Get the receiver from the stack. |
| 1510 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 1522 __a movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 1511 | 1523 |
| 1512 | 1524 |
| 1513 // Check that the maps haven't changed. | 1525 // Check that the maps haven't changed. |
| 1514 __ JumpIfSmi(rdx, miss); | 1526 __ JumpIfSmi(rdx, miss); |
| 1515 CheckPrototypes(object, rdx, holder, rbx, rax, rdi, name, miss); | 1527 CheckPrototypes(object, rdx, holder, rbx, rax, rdi, name, miss); |
| 1516 } | 1528 } |
| 1517 | 1529 |
| 1518 | 1530 |
| 1519 void CallStubCompiler::GenerateLoadFunctionFromCell( | 1531 void CallStubCompiler::GenerateLoadFunctionFromCell( |
| 1520 Handle<Cell> cell, | 1532 Handle<Cell> cell, |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1566 // ... | 1578 // ... |
| 1567 // rsp[argc * 8] : argument 1 | 1579 // rsp[argc * 8] : argument 1 |
| 1568 // rsp[(argc + 1) * 8] : argument 0 = receiver | 1580 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 1569 // ----------------------------------- | 1581 // ----------------------------------- |
| 1570 Label miss; | 1582 Label miss; |
| 1571 | 1583 |
| 1572 GenerateNameCheck(name, &miss); | 1584 GenerateNameCheck(name, &miss); |
| 1573 | 1585 |
| 1574 // Get the receiver from the stack. | 1586 // Get the receiver from the stack. |
| 1575 const int argc = arguments().immediate(); | 1587 const int argc = arguments().immediate(); |
| 1576 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 1588 __a movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 1577 | 1589 |
| 1578 // Check that the receiver isn't a smi. | 1590 // Check that the receiver isn't a smi. |
| 1579 __ JumpIfSmi(rdx, &miss); | 1591 __ JumpIfSmi(rdx, &miss); |
| 1580 | 1592 |
| 1581 // Do the right check and compute the holder register. | 1593 // Do the right check and compute the holder register. |
| 1582 Register reg = CheckPrototypes(object, rdx, holder, rbx, rax, rdi, | 1594 Register reg = CheckPrototypes(object, rdx, holder, rbx, rax, rdi, |
| 1583 name, &miss); | 1595 name, &miss); |
| 1584 | 1596 |
| 1585 GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder), | 1597 GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder), |
| 1586 index.translate(holder), Representation::Tagged()); | 1598 index.translate(holder), Representation::Tagged()); |
| 1587 | 1599 |
| 1588 // Check that the function really is a function. | 1600 // Check that the function really is a function. |
| 1589 __ JumpIfSmi(rdi, &miss); | 1601 __ JumpIfSmi(rdi, &miss); |
| 1590 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx); | 1602 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx); |
| 1591 __ j(not_equal, &miss); | 1603 __ j(not_equal, &miss); |
| 1592 | 1604 |
| 1593 // Patch the receiver on the stack with the global proxy if | 1605 // Patch the receiver on the stack with the global proxy if |
| 1594 // necessary. | 1606 // necessary. |
| 1595 if (object->IsGlobalObject()) { | 1607 if (object->IsGlobalObject()) { |
| 1596 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 1608 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 1597 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 1609 __a movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
| 1598 } | 1610 } |
| 1599 | 1611 |
| 1600 // Invoke the function. | 1612 // Invoke the function. |
| 1601 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 1613 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 1602 ? CALL_AS_FUNCTION | 1614 ? CALL_AS_FUNCTION |
| 1603 : CALL_AS_METHOD; | 1615 : CALL_AS_METHOD; |
| 1604 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, | 1616 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, |
| 1605 NullCallWrapper(), call_kind); | 1617 NullCallWrapper(), call_kind); |
| 1606 | 1618 |
| 1607 // Handle call cache miss. | 1619 // Handle call cache miss. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1621 Handle<String> name, | 1633 Handle<String> name, |
| 1622 Code::StubType type) { | 1634 Code::StubType type) { |
| 1623 Label miss; | 1635 Label miss; |
| 1624 | 1636 |
| 1625 // Check that function is still array | 1637 // Check that function is still array |
| 1626 const int argc = arguments().immediate(); | 1638 const int argc = arguments().immediate(); |
| 1627 GenerateNameCheck(name, &miss); | 1639 GenerateNameCheck(name, &miss); |
| 1628 | 1640 |
| 1629 if (cell.is_null()) { | 1641 if (cell.is_null()) { |
| 1630 // Get the receiver from the stack. | 1642 // Get the receiver from the stack. |
| 1631 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 1643 __a movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 1632 | 1644 |
| 1633 // Check that the receiver isn't a smi. | 1645 // Check that the receiver isn't a smi. |
| 1634 __ JumpIfSmi(rdx, &miss); | 1646 __ JumpIfSmi(rdx, &miss); |
| 1635 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 1647 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, |
| 1636 name, &miss); | 1648 name, &miss); |
| 1637 } else { | 1649 } else { |
| 1638 ASSERT(cell->value() == *function); | 1650 ASSERT(cell->value() == *function); |
| 1639 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 1651 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 1640 &miss); | 1652 &miss); |
| 1641 GenerateLoadFunctionFromCell(cell, function, &miss); | 1653 GenerateLoadFunctionFromCell(cell, function, &miss); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1675 // ----------------------------------- | 1687 // ----------------------------------- |
| 1676 | 1688 |
| 1677 // If object is not an array, bail out to regular call. | 1689 // If object is not an array, bail out to regular call. |
| 1678 if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); | 1690 if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); |
| 1679 | 1691 |
| 1680 Label miss; | 1692 Label miss; |
| 1681 GenerateNameCheck(name, &miss); | 1693 GenerateNameCheck(name, &miss); |
| 1682 | 1694 |
| 1683 // Get the receiver from the stack. | 1695 // Get the receiver from the stack. |
| 1684 const int argc = arguments().immediate(); | 1696 const int argc = arguments().immediate(); |
| 1685 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 1697 __a movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 1686 | 1698 |
| 1687 // Check that the receiver isn't a smi. | 1699 // Check that the receiver isn't a smi. |
| 1688 __ JumpIfSmi(rdx, &miss); | 1700 __ JumpIfSmi(rdx, &miss); |
| 1689 | 1701 |
| 1690 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 1702 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, |
| 1691 name, &miss); | 1703 name, &miss); |
| 1692 | 1704 |
| 1693 if (argc == 0) { | 1705 if (argc == 0) { |
| 1694 // Noop, return the length. | 1706 // Noop, return the length. |
| 1695 __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset)); | 1707 __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset)); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1714 __ addl(rax, Immediate(argc)); | 1726 __ addl(rax, Immediate(argc)); |
| 1715 | 1727 |
| 1716 // Get the elements' length into rcx. | 1728 // Get the elements' length into rcx. |
| 1717 __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); | 1729 __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); |
| 1718 | 1730 |
| 1719 // Check if we could survive without allocation. | 1731 // Check if we could survive without allocation. |
| 1720 __ cmpl(rax, rcx); | 1732 __ cmpl(rax, rcx); |
| 1721 __ j(greater, &attempt_to_grow_elements); | 1733 __ j(greater, &attempt_to_grow_elements); |
| 1722 | 1734 |
| 1723 // Check if value is a smi. | 1735 // Check if value is a smi. |
| 1724 __ movq(rcx, Operand(rsp, argc * kPointerSize)); | 1736 __a movq(rcx, Operand(rsp, argc * kPointerSize)); |
| 1725 __ JumpIfNotSmi(rcx, &with_write_barrier); | 1737 __ JumpIfNotSmi(rcx, &with_write_barrier); |
| 1726 | 1738 |
| 1727 // Save new length. | 1739 // Save new length. |
| 1728 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax); | 1740 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax); |
| 1729 | 1741 |
| 1730 // Store the value. | 1742 // Store the value. |
| 1731 __ movq(FieldOperand(rdi, | 1743 __ movq(FieldOperand(rdi, |
| 1732 rax, | 1744 rax, |
| 1733 times_pointer_size, | 1745 times_pointer_size, |
| 1734 FixedArray::kHeaderSize - argc * kPointerSize), | 1746 FixedArray::kHeaderSize - argc * kPointerSize), |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1749 STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue); | 1761 STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue); |
| 1750 __ addl(rax, Immediate(argc)); | 1762 __ addl(rax, Immediate(argc)); |
| 1751 | 1763 |
| 1752 // Get the elements' length into rcx. | 1764 // Get the elements' length into rcx. |
| 1753 __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); | 1765 __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); |
| 1754 | 1766 |
| 1755 // Check if we could survive without allocation. | 1767 // Check if we could survive without allocation. |
| 1756 __ cmpl(rax, rcx); | 1768 __ cmpl(rax, rcx); |
| 1757 __ j(greater, &call_builtin); | 1769 __ j(greater, &call_builtin); |
| 1758 | 1770 |
| 1759 __ movq(rcx, Operand(rsp, argc * kPointerSize)); | 1771 __a movq(rcx, Operand(rsp, argc * kPointerSize)); |
| 1760 __ StoreNumberToDoubleElements( | 1772 __ StoreNumberToDoubleElements( |
| 1761 rcx, rdi, rax, xmm0, &call_builtin, argc * kDoubleSize); | 1773 rcx, rdi, rax, xmm0, &call_builtin, argc * kDoubleSize); |
| 1762 | 1774 |
| 1763 // Save new length. | 1775 // Save new length. |
| 1764 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax); | 1776 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax); |
| 1765 __ Integer32ToSmi(rax, rax); // Return new length as smi. | 1777 __ Integer32ToSmi(rax, rax); // Return new length as smi. |
| 1766 __ ret((argc + 1) * kPointerSize); | 1778 __ ret((argc + 1) * kPointerSize); |
| 1767 | 1779 |
| 1768 __ bind(&with_write_barrier); | 1780 __ bind(&with_write_barrier); |
| 1769 | 1781 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1826 OMIT_SMI_CHECK); | 1838 OMIT_SMI_CHECK); |
| 1827 | 1839 |
| 1828 __ Integer32ToSmi(rax, rax); // Return new length as smi. | 1840 __ Integer32ToSmi(rax, rax); // Return new length as smi. |
| 1829 __ ret((argc + 1) * kPointerSize); | 1841 __ ret((argc + 1) * kPointerSize); |
| 1830 | 1842 |
| 1831 __ bind(&attempt_to_grow_elements); | 1843 __ bind(&attempt_to_grow_elements); |
| 1832 if (!FLAG_inline_new) { | 1844 if (!FLAG_inline_new) { |
| 1833 __ jmp(&call_builtin); | 1845 __ jmp(&call_builtin); |
| 1834 } | 1846 } |
| 1835 | 1847 |
| 1836 __ movq(rbx, Operand(rsp, argc * kPointerSize)); | 1848 __a movq(rbx, Operand(rsp, argc * kPointerSize)); |
| 1837 // Growing elements that are SMI-only requires special handling in case | 1849 // Growing elements that are SMI-only requires special handling in case |
| 1838 // the new element is non-Smi. For now, delegate to the builtin. | 1850 // the new element is non-Smi. For now, delegate to the builtin. |
| 1839 Label no_fast_elements_check; | 1851 Label no_fast_elements_check; |
| 1840 __ JumpIfSmi(rbx, &no_fast_elements_check); | 1852 __ JumpIfSmi(rbx, &no_fast_elements_check); |
| 1841 __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); | 1853 __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); |
| 1842 __ CheckFastObjectElements(rcx, &call_builtin, Label::kFar); | 1854 __ CheckFastObjectElements(rcx, &call_builtin, Label::kFar); |
| 1843 __ bind(&no_fast_elements_check); | 1855 __ bind(&no_fast_elements_check); |
| 1844 | 1856 |
| 1845 ExternalReference new_space_allocation_top = | 1857 ExternalReference new_space_allocation_top = |
| 1846 ExternalReference::new_space_allocation_top_address(isolate()); | 1858 ExternalReference::new_space_allocation_top_address(isolate()); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1875 } | 1887 } |
| 1876 | 1888 |
| 1877 // We know the elements array is in new space so we don't need the | 1889 // We know the elements array is in new space so we don't need the |
| 1878 // remembered set, but we just pushed a value onto it so we may have to | 1890 // remembered set, but we just pushed a value onto it so we may have to |
| 1879 // tell the incremental marker to rescan the object that we just grew. We | 1891 // tell the incremental marker to rescan the object that we just grew. We |
| 1880 // don't need to worry about the holes because they are in old space and | 1892 // don't need to worry about the holes because they are in old space and |
| 1881 // already marked black. | 1893 // already marked black. |
| 1882 __ RecordWrite(rdi, rdx, rbx, kDontSaveFPRegs, OMIT_REMEMBERED_SET); | 1894 __ RecordWrite(rdi, rdx, rbx, kDontSaveFPRegs, OMIT_REMEMBERED_SET); |
| 1883 | 1895 |
| 1884 // Restore receiver to rdx as finish sequence assumes it's here. | 1896 // Restore receiver to rdx as finish sequence assumes it's here. |
| 1885 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 1897 __a movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 1886 | 1898 |
| 1887 // Increment element's and array's sizes. | 1899 // Increment element's and array's sizes. |
| 1888 __ SmiAddConstant(FieldOperand(rdi, FixedArray::kLengthOffset), | 1900 __ SmiAddConstant(FieldOperand(rdi, FixedArray::kLengthOffset), |
| 1889 Smi::FromInt(kAllocationDelta)); | 1901 Smi::FromInt(kAllocationDelta)); |
| 1890 | 1902 |
| 1891 // Make new length a smi before returning it. | 1903 // Make new length a smi before returning it. |
| 1892 __ Integer32ToSmi(rax, rax); | 1904 __ Integer32ToSmi(rax, rax); |
| 1893 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax); | 1905 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax); |
| 1894 | 1906 |
| 1895 __ ret((argc + 1) * kPointerSize); | 1907 __ ret((argc + 1) * kPointerSize); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1926 // ----------------------------------- | 1938 // ----------------------------------- |
| 1927 | 1939 |
| 1928 // If object is not an array, bail out to regular call. | 1940 // If object is not an array, bail out to regular call. |
| 1929 if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); | 1941 if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); |
| 1930 | 1942 |
| 1931 Label miss, return_undefined, call_builtin; | 1943 Label miss, return_undefined, call_builtin; |
| 1932 GenerateNameCheck(name, &miss); | 1944 GenerateNameCheck(name, &miss); |
| 1933 | 1945 |
| 1934 // Get the receiver from the stack. | 1946 // Get the receiver from the stack. |
| 1935 const int argc = arguments().immediate(); | 1947 const int argc = arguments().immediate(); |
| 1936 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 1948 __a movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 1937 | 1949 |
| 1938 // Check that the receiver isn't a smi. | 1950 // Check that the receiver isn't a smi. |
| 1939 __ JumpIfSmi(rdx, &miss); | 1951 __ JumpIfSmi(rdx, &miss); |
| 1940 | 1952 |
| 1941 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 1953 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, |
| 1942 name, &miss); | 1954 name, &miss); |
| 1943 | 1955 |
| 1944 // Get the elements array of the object. | 1956 // Get the elements array of the object. |
| 1945 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); | 1957 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); |
| 1946 | 1958 |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2029 rax, | 2041 rax, |
| 2030 &miss); | 2042 &miss); |
| 2031 ASSERT(!object.is_identical_to(holder)); | 2043 ASSERT(!object.is_identical_to(holder)); |
| 2032 CheckPrototypes( | 2044 CheckPrototypes( |
| 2033 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2045 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), |
| 2034 rax, holder, rbx, rdx, rdi, name, &miss); | 2046 rax, holder, rbx, rdx, rdi, name, &miss); |
| 2035 | 2047 |
| 2036 Register receiver = rbx; | 2048 Register receiver = rbx; |
| 2037 Register index = rdi; | 2049 Register index = rdi; |
| 2038 Register result = rax; | 2050 Register result = rax; |
| 2039 __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize)); | 2051 __a movq(receiver, Operand(rsp, (argc + 1) * kPointerSize)); |
| 2040 if (argc > 0) { | 2052 if (argc > 0) { |
| 2041 __ movq(index, Operand(rsp, (argc - 0) * kPointerSize)); | 2053 __a movq(index, Operand(rsp, (argc - 0) * kPointerSize)); |
| 2042 } else { | 2054 } else { |
| 2043 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 2055 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
| 2044 } | 2056 } |
| 2045 | 2057 |
| 2046 StringCharCodeAtGenerator generator(receiver, | 2058 StringCharCodeAtGenerator generator(receiver, |
| 2047 index, | 2059 index, |
| 2048 result, | 2060 result, |
| 2049 &miss, // When not a string. | 2061 &miss, // When not a string. |
| 2050 &miss, // When not a number. | 2062 &miss, // When not a number. |
| 2051 index_out_of_range_label, | 2063 index_out_of_range_label, |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2110 &miss); | 2122 &miss); |
| 2111 ASSERT(!object.is_identical_to(holder)); | 2123 ASSERT(!object.is_identical_to(holder)); |
| 2112 CheckPrototypes( | 2124 CheckPrototypes( |
| 2113 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2125 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), |
| 2114 rax, holder, rbx, rdx, rdi, name, &miss); | 2126 rax, holder, rbx, rdx, rdi, name, &miss); |
| 2115 | 2127 |
| 2116 Register receiver = rax; | 2128 Register receiver = rax; |
| 2117 Register index = rdi; | 2129 Register index = rdi; |
| 2118 Register scratch = rdx; | 2130 Register scratch = rdx; |
| 2119 Register result = rax; | 2131 Register result = rax; |
| 2120 __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize)); | 2132 __a movq(receiver, Operand(rsp, (argc + 1) * kPointerSize)); |
| 2121 if (argc > 0) { | 2133 if (argc > 0) { |
| 2122 __ movq(index, Operand(rsp, (argc - 0) * kPointerSize)); | 2134 __a movq(index, Operand(rsp, (argc - 0) * kPointerSize)); |
| 2123 } else { | 2135 } else { |
| 2124 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 2136 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
| 2125 } | 2137 } |
| 2126 | 2138 |
| 2127 StringCharAtGenerator generator(receiver, | 2139 StringCharAtGenerator generator(receiver, |
| 2128 index, | 2140 index, |
| 2129 scratch, | 2141 scratch, |
| 2130 result, | 2142 result, |
| 2131 &miss, // When not a string. | 2143 &miss, // When not a string. |
| 2132 &miss, // When not a number. | 2144 &miss, // When not a number. |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2171 | 2183 |
| 2172 // If the object is not a JSObject or we got an unexpected number of | 2184 // If the object is not a JSObject or we got an unexpected number of |
| 2173 // arguments, bail out to the regular call. | 2185 // arguments, bail out to the regular call. |
| 2174 const int argc = arguments().immediate(); | 2186 const int argc = arguments().immediate(); |
| 2175 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2187 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2176 | 2188 |
| 2177 Label miss; | 2189 Label miss; |
| 2178 GenerateNameCheck(name, &miss); | 2190 GenerateNameCheck(name, &miss); |
| 2179 | 2191 |
| 2180 if (cell.is_null()) { | 2192 if (cell.is_null()) { |
| 2181 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); | 2193 __a movq(rdx, Operand(rsp, 2 * kPointerSize)); |
| 2182 __ JumpIfSmi(rdx, &miss); | 2194 __ JumpIfSmi(rdx, &miss); |
| 2183 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 2195 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, |
| 2184 name, &miss); | 2196 name, &miss); |
| 2185 } else { | 2197 } else { |
| 2186 ASSERT(cell->value() == *function); | 2198 ASSERT(cell->value() == *function); |
| 2187 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 2199 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 2188 &miss); | 2200 &miss); |
| 2189 GenerateLoadFunctionFromCell(cell, function, &miss); | 2201 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2190 } | 2202 } |
| 2191 | 2203 |
| 2192 // Load the char code argument. | 2204 // Load the char code argument. |
| 2193 Register code = rbx; | 2205 Register code = rbx; |
| 2194 __ movq(code, Operand(rsp, 1 * kPointerSize)); | 2206 __a movq(code, Operand(rsp, 1 * kPointerSize)); |
| 2195 | 2207 |
| 2196 // Check the code is a smi. | 2208 // Check the code is a smi. |
| 2197 Label slow; | 2209 Label slow; |
| 2198 __ JumpIfNotSmi(code, &slow); | 2210 __ JumpIfNotSmi(code, &slow); |
| 2199 | 2211 |
| 2200 // Convert the smi code to uint16. | 2212 // Convert the smi code to uint16. |
| 2201 __ SmiAndConstant(code, code, Smi::FromInt(0xffff)); | 2213 __ SmiAndConstant(code, code, Smi::FromInt(0xffff)); |
| 2202 | 2214 |
| 2203 StringCharFromCodeGenerator generator(code, rax); | 2215 StringCharFromCodeGenerator generator(code, rax); |
| 2204 generator.GenerateFast(masm()); | 2216 generator.GenerateFast(masm()); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2255 | 2267 |
| 2256 // If the object is not a JSObject or we got an unexpected number of | 2268 // If the object is not a JSObject or we got an unexpected number of |
| 2257 // arguments, bail out to the regular call. | 2269 // arguments, bail out to the regular call. |
| 2258 const int argc = arguments().immediate(); | 2270 const int argc = arguments().immediate(); |
| 2259 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2271 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2260 | 2272 |
| 2261 Label miss; | 2273 Label miss; |
| 2262 GenerateNameCheck(name, &miss); | 2274 GenerateNameCheck(name, &miss); |
| 2263 | 2275 |
| 2264 if (cell.is_null()) { | 2276 if (cell.is_null()) { |
| 2265 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); | 2277 __a movq(rdx, Operand(rsp, 2 * kPointerSize)); |
| 2266 __ JumpIfSmi(rdx, &miss); | 2278 __ JumpIfSmi(rdx, &miss); |
| 2267 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 2279 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, |
| 2268 name, &miss); | 2280 name, &miss); |
| 2269 } else { | 2281 } else { |
| 2270 ASSERT(cell->value() == *function); | 2282 ASSERT(cell->value() == *function); |
| 2271 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 2283 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 2272 &miss); | 2284 &miss); |
| 2273 GenerateLoadFunctionFromCell(cell, function, &miss); | 2285 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2274 } | 2286 } |
| 2275 // Load the (only) argument into rax. | 2287 // Load the (only) argument into rax. |
| 2276 __ movq(rax, Operand(rsp, 1 * kPointerSize)); | 2288 __a movq(rax, Operand(rsp, 1 * kPointerSize)); |
| 2277 | 2289 |
| 2278 // Check if the argument is a smi. | 2290 // Check if the argument is a smi. |
| 2279 Label not_smi; | 2291 Label not_smi; |
| 2280 STATIC_ASSERT(kSmiTag == 0); | 2292 STATIC_ASSERT(kSmiTag == 0); |
| 2281 __ JumpIfNotSmi(rax, ¬_smi); | 2293 __ JumpIfNotSmi(rax, ¬_smi); |
| 2282 __ SmiToInteger32(rax, rax); | 2294 __ SmiToInteger32(rax, rax); |
| 2283 | 2295 |
| 2284 // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0 | 2296 // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0 |
| 2285 // otherwise. | 2297 // otherwise. |
| 2286 __ movl(rbx, rax); | 2298 __ movl(rbx, rax); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2297 Label slow; | 2309 Label slow; |
| 2298 __ j(negative, &slow); | 2310 __ j(negative, &slow); |
| 2299 | 2311 |
| 2300 // Smi case done. | 2312 // Smi case done. |
| 2301 __ Integer32ToSmi(rax, rax); | 2313 __ Integer32ToSmi(rax, rax); |
| 2302 __ ret(2 * kPointerSize); | 2314 __ ret(2 * kPointerSize); |
| 2303 | 2315 |
| 2304 // Check if the argument is a heap number and load its value. | 2316 // Check if the argument is a heap number and load its value. |
| 2305 __ bind(¬_smi); | 2317 __ bind(¬_smi); |
| 2306 __ CheckMap(rax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK); | 2318 __ CheckMap(rax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK); |
| 2307 __ movq(rbx, FieldOperand(rax, HeapNumber::kValueOffset)); | 2319 __k movq(rbx, FieldOperand(rax, HeapNumber::kValueOffset)); |
| 2308 | 2320 |
| 2309 // Check the sign of the argument. If the argument is positive, | 2321 // Check the sign of the argument. If the argument is positive, |
| 2310 // just return it. | 2322 // just return it. |
| 2311 Label negative_sign; | 2323 Label negative_sign; |
| 2312 const int sign_mask_shift = | 2324 const int sign_mask_shift = |
| 2313 (HeapNumber::kExponentOffset - HeapNumber::kValueOffset) * kBitsPerByte; | 2325 (HeapNumber::kExponentOffset - HeapNumber::kValueOffset) * kBitsPerByte; |
| 2314 __ movq(rdi, static_cast<int64_t>(HeapNumber::kSignMask) << sign_mask_shift, | 2326 __k movq(rdi, static_cast<int64_t>(HeapNumber::kSignMask) << sign_mask_shift, |
| 2315 RelocInfo::NONE64); | 2327 RelocInfo::NONE64); |
| 2316 __ testq(rbx, rdi); | 2328 __k testq(rbx, rdi); |
| 2317 __ j(not_zero, &negative_sign); | 2329 __ j(not_zero, &negative_sign); |
| 2318 __ ret(2 * kPointerSize); | 2330 __ ret(2 * kPointerSize); |
| 2319 | 2331 |
| 2320 // If the argument is negative, clear the sign, and return a new | 2332 // If the argument is negative, clear the sign, and return a new |
| 2321 // number. We still have the sign mask in rdi. | 2333 // number. We still have the sign mask in rdi. |
| 2322 __ bind(&negative_sign); | 2334 __ bind(&negative_sign); |
| 2323 __ xor_(rbx, rdi); | 2335 __k xor_(rbx, rdi); |
| 2324 __ AllocateHeapNumber(rax, rdx, &slow); | 2336 __ AllocateHeapNumber(rax, rdx, &slow); |
| 2325 __ movq(FieldOperand(rax, HeapNumber::kValueOffset), rbx); | 2337 __k movq(FieldOperand(rax, HeapNumber::kValueOffset), rbx); |
| 2326 __ ret(2 * kPointerSize); | 2338 __ ret(2 * kPointerSize); |
| 2327 | 2339 |
| 2328 // Tail call the full function. We do not have to patch the receiver | 2340 // Tail call the full function. We do not have to patch the receiver |
| 2329 // because the function makes no use of it. | 2341 // because the function makes no use of it. |
| 2330 __ bind(&slow); | 2342 __ bind(&slow); |
| 2331 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2343 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2332 ? CALL_AS_FUNCTION | 2344 ? CALL_AS_FUNCTION |
| 2333 : CALL_AS_METHOD; | 2345 : CALL_AS_METHOD; |
| 2334 ParameterCount expected(function); | 2346 ParameterCount expected(function); |
| 2335 __ InvokeFunction(function, expected, arguments(), | 2347 __ InvokeFunction(function, expected, arguments(), |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2359 if (!object->IsJSObject()) return Handle<Code>::null(); | 2371 if (!object->IsJSObject()) return Handle<Code>::null(); |
| 2360 int depth = optimization.GetPrototypeDepthOfExpectedType( | 2372 int depth = optimization.GetPrototypeDepthOfExpectedType( |
| 2361 Handle<JSObject>::cast(object), holder); | 2373 Handle<JSObject>::cast(object), holder); |
| 2362 if (depth == kInvalidProtoDepth) return Handle<Code>::null(); | 2374 if (depth == kInvalidProtoDepth) return Handle<Code>::null(); |
| 2363 | 2375 |
| 2364 Label miss, miss_before_stack_reserved; | 2376 Label miss, miss_before_stack_reserved; |
| 2365 GenerateNameCheck(name, &miss_before_stack_reserved); | 2377 GenerateNameCheck(name, &miss_before_stack_reserved); |
| 2366 | 2378 |
| 2367 // Get the receiver from the stack. | 2379 // Get the receiver from the stack. |
| 2368 const int argc = arguments().immediate(); | 2380 const int argc = arguments().immediate(); |
| 2369 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 2381 __a movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 2370 | 2382 |
| 2371 // Check that the receiver isn't a smi. | 2383 // Check that the receiver isn't a smi. |
| 2372 __ JumpIfSmi(rdx, &miss_before_stack_reserved); | 2384 __ JumpIfSmi(rdx, &miss_before_stack_reserved); |
| 2373 | 2385 |
| 2374 Counters* counters = isolate()->counters(); | 2386 Counters* counters = isolate()->counters(); |
| 2375 __ IncrementCounter(counters->call_const(), 1); | 2387 __ IncrementCounter(counters->call_const(), 1); |
| 2376 __ IncrementCounter(counters->call_const_fast_api(), 1); | 2388 __ IncrementCounter(counters->call_const_fast_api(), 1); |
| 2377 | 2389 |
| 2378 // Allocate space for v8::Arguments implicit values. Must be initialized | 2390 // Allocate space for v8::Arguments implicit values. Must be initialized |
| 2379 // before calling any runtime function. | 2391 // before calling any runtime function. |
| 2380 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); | 2392 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2381 | 2393 |
| 2382 // Check that the maps haven't changed and find a Holder as a side effect. | 2394 // Check that the maps haven't changed and find a Holder as a side effect. |
| 2383 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 2395 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, |
| 2384 name, depth, &miss); | 2396 name, depth, &miss); |
| 2385 | 2397 |
| 2386 // Move the return address on top of the stack. | 2398 // Move the return address on top of the stack. |
| 2387 __ movq(rax, Operand(rsp, kFastApiCallArguments * kPointerSize)); | 2399 __k movq(rax, Operand(rsp, kFastApiCallArguments * kPointerSize)); |
| 2388 __ movq(Operand(rsp, 0 * kPointerSize), rax); | 2400 __k movq(Operand(rsp, 0 * kPointerSize), rax); |
| 2389 | 2401 |
| 2390 GenerateFastApiCall(masm(), optimization, argc); | 2402 GenerateFastApiCall(masm(), optimization, argc); |
| 2391 | 2403 |
| 2392 __ bind(&miss); | 2404 __ bind(&miss); |
| 2393 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); | 2405 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2394 | 2406 |
| 2395 __ bind(&miss_before_stack_reserved); | 2407 __ bind(&miss_before_stack_reserved); |
| 2396 GenerateMissBranch(); | 2408 GenerateMissBranch(); |
| 2397 | 2409 |
| 2398 // Return the generated code. | 2410 // Return the generated code. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2412 // rsp[16] : argument argc - 1 | 2424 // rsp[16] : argument argc - 1 |
| 2413 // ... | 2425 // ... |
| 2414 // rsp[argc * 8] : argument 1 | 2426 // rsp[argc * 8] : argument 1 |
| 2415 // rsp[(argc + 1) * 8] : argument 0 = receiver | 2427 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 2416 // ----------------------------------- | 2428 // ----------------------------------- |
| 2417 Label miss; | 2429 Label miss; |
| 2418 GenerateNameCheck(name, &miss); | 2430 GenerateNameCheck(name, &miss); |
| 2419 | 2431 |
| 2420 // Get the receiver from the stack. | 2432 // Get the receiver from the stack. |
| 2421 const int argc = arguments().immediate(); | 2433 const int argc = arguments().immediate(); |
| 2422 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 2434 __a movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 2423 | 2435 |
| 2424 // Check that the receiver isn't a smi. | 2436 // Check that the receiver isn't a smi. |
| 2425 if (check != NUMBER_CHECK) { | 2437 if (check != NUMBER_CHECK) { |
| 2426 __ JumpIfSmi(rdx, &miss); | 2438 __ JumpIfSmi(rdx, &miss); |
| 2427 } | 2439 } |
| 2428 | 2440 |
| 2429 // Make sure that it's okay not to patch the on stack receiver | 2441 // Make sure that it's okay not to patch the on stack receiver |
| 2430 // unless we're doing a receiver map check. | 2442 // unless we're doing a receiver map check. |
| 2431 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2443 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
| 2432 | 2444 |
| 2433 Counters* counters = isolate()->counters(); | 2445 Counters* counters = isolate()->counters(); |
| 2434 switch (check) { | 2446 switch (check) { |
| 2435 case RECEIVER_MAP_CHECK: | 2447 case RECEIVER_MAP_CHECK: |
| 2436 __ IncrementCounter(counters->call_const(), 1); | 2448 __ IncrementCounter(counters->call_const(), 1); |
| 2437 | 2449 |
| 2438 // Check that the maps haven't changed. | 2450 // Check that the maps haven't changed. |
| 2439 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, | 2451 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, |
| 2440 rdi, name, &miss); | 2452 rdi, name, &miss); |
| 2441 | 2453 |
| 2442 // Patch the receiver on the stack with the global proxy if | 2454 // Patch the receiver on the stack with the global proxy if |
| 2443 // necessary. | 2455 // necessary. |
| 2444 if (object->IsGlobalObject()) { | 2456 if (object->IsGlobalObject()) { |
| 2445 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 2457 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 2446 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 2458 __a movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
| 2447 } | 2459 } |
| 2448 break; | 2460 break; |
| 2449 | 2461 |
| 2450 case STRING_CHECK: | 2462 case STRING_CHECK: |
| 2451 // Check that the object is a string. | 2463 // Check that the object is a string. |
| 2452 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax); | 2464 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax); |
| 2453 __ j(above_equal, &miss); | 2465 __ j(above_equal, &miss); |
| 2454 // Check that the maps starting from the prototype haven't changed. | 2466 // Check that the maps starting from the prototype haven't changed. |
| 2455 GenerateDirectLoadGlobalFunctionPrototype( | 2467 GenerateDirectLoadGlobalFunctionPrototype( |
| 2456 masm(), Context::STRING_FUNCTION_INDEX, rax, &miss); | 2468 masm(), Context::STRING_FUNCTION_INDEX, rax, &miss); |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2563 Label miss; | 2575 Label miss; |
| 2564 GenerateNameCheck(name, &miss); | 2576 GenerateNameCheck(name, &miss); |
| 2565 | 2577 |
| 2566 // Get the number of arguments. | 2578 // Get the number of arguments. |
| 2567 const int argc = arguments().immediate(); | 2579 const int argc = arguments().immediate(); |
| 2568 | 2580 |
| 2569 LookupResult lookup(isolate()); | 2581 LookupResult lookup(isolate()); |
| 2570 LookupPostInterceptor(holder, name, &lookup); | 2582 LookupPostInterceptor(holder, name, &lookup); |
| 2571 | 2583 |
| 2572 // Get the receiver from the stack. | 2584 // Get the receiver from the stack. |
| 2573 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 2585 __a movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 2574 | 2586 |
| 2575 CallInterceptorCompiler compiler(this, arguments(), rcx, extra_state_); | 2587 CallInterceptorCompiler compiler(this, arguments(), rcx, extra_state_); |
| 2576 compiler.Compile(masm(), object, holder, name, &lookup, rdx, rbx, rdi, rax, | 2588 compiler.Compile(masm(), object, holder, name, &lookup, rdx, rbx, rdi, rax, |
| 2577 &miss); | 2589 &miss); |
| 2578 | 2590 |
| 2579 // Restore receiver. | 2591 // Restore receiver. |
| 2580 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 2592 __a movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 2581 | 2593 |
| 2582 // Check that the function really is a function. | 2594 // Check that the function really is a function. |
| 2583 __ JumpIfSmi(rax, &miss); | 2595 __ JumpIfSmi(rax, &miss); |
| 2584 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); | 2596 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); |
| 2585 __ j(not_equal, &miss); | 2597 __ j(not_equal, &miss); |
| 2586 | 2598 |
| 2587 // Patch the receiver on the stack with the global proxy if | 2599 // Patch the receiver on the stack with the global proxy if |
| 2588 // necessary. | 2600 // necessary. |
| 2589 if (object->IsGlobalObject()) { | 2601 if (object->IsGlobalObject()) { |
| 2590 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 2602 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 2591 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 2603 __a movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
| 2592 } | 2604 } |
| 2593 | 2605 |
| 2594 // Invoke the function. | 2606 // Invoke the function. |
| 2595 __ movq(rdi, rax); | 2607 __ movq(rdi, rax); |
| 2596 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2608 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2597 ? CALL_AS_FUNCTION | 2609 ? CALL_AS_FUNCTION |
| 2598 : CALL_AS_METHOD; | 2610 : CALL_AS_METHOD; |
| 2599 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, | 2611 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, |
| 2600 NullCallWrapper(), call_kind); | 2612 NullCallWrapper(), call_kind); |
| 2601 | 2613 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2636 GenerateNameCheck(name, &miss); | 2648 GenerateNameCheck(name, &miss); |
| 2637 | 2649 |
| 2638 // Get the number of arguments. | 2650 // Get the number of arguments. |
| 2639 const int argc = arguments().immediate(); | 2651 const int argc = arguments().immediate(); |
| 2640 GenerateGlobalReceiverCheck(object, holder, name, &miss); | 2652 GenerateGlobalReceiverCheck(object, holder, name, &miss); |
| 2641 GenerateLoadFunctionFromCell(cell, function, &miss); | 2653 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2642 | 2654 |
| 2643 // Patch the receiver on the stack with the global proxy. | 2655 // Patch the receiver on the stack with the global proxy. |
| 2644 if (object->IsGlobalObject()) { | 2656 if (object->IsGlobalObject()) { |
| 2645 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 2657 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 2646 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 2658 __a movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
| 2647 } | 2659 } |
| 2648 | 2660 |
| 2649 // Set up the context (function already in rdi). | 2661 // Set up the context (function already in rdi). |
| 2650 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | 2662 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
| 2651 | 2663 |
| 2652 // Jump to the cached code (tail call). | 2664 // Jump to the cached code (tail call). |
| 2653 Counters* counters = isolate()->counters(); | 2665 Counters* counters = isolate()->counters(); |
| 2654 __ IncrementCounter(counters->call_global_inline(), 1); | 2666 __ IncrementCounter(counters->call_global_inline(), 1); |
| 2655 ParameterCount expected(function->shared()->formal_parameter_count()); | 2667 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 2656 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2668 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2680 Handle<ExecutableAccessorInfo> callback) { | 2692 Handle<ExecutableAccessorInfo> callback) { |
| 2681 Label miss; | 2693 Label miss; |
| 2682 // Check that the maps haven't changed. | 2694 // Check that the maps haven't changed. |
| 2683 __ JumpIfSmi(receiver(), &miss); | 2695 __ JumpIfSmi(receiver(), &miss); |
| 2684 CheckPrototypes(object, receiver(), holder, | 2696 CheckPrototypes(object, receiver(), holder, |
| 2685 scratch1(), scratch2(), scratch3(), name, &miss); | 2697 scratch1(), scratch2(), scratch3(), name, &miss); |
| 2686 | 2698 |
| 2687 // Stub never generated for non-global objects that require access checks. | 2699 // Stub never generated for non-global objects that require access checks. |
| 2688 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 2700 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
| 2689 | 2701 |
| 2690 __ pop(scratch1()); // remove the return address | 2702 __k pop(scratch1()); // remove the return address |
| 2691 __ push(receiver()); | 2703 __ push(receiver()); |
| 2692 __ Push(callback); // callback info | 2704 __ Push(callback); // callback info |
| 2693 __ push(this->name()); | 2705 __ push(this->name()); |
| 2694 __ push(value()); | 2706 __ push(value()); |
| 2695 __ push(scratch1()); // restore return address | 2707 __k push(scratch1()); // restore return address |
| 2696 | 2708 |
| 2697 // Do tail-call to the runtime system. | 2709 // Do tail-call to the runtime system. |
| 2698 ExternalReference store_callback_property = | 2710 ExternalReference store_callback_property = |
| 2699 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 2711 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
| 2700 __ TailCallExternalReference(store_callback_property, 4, 1); | 2712 __ TailCallExternalReference(store_callback_property, 4, 1); |
| 2701 | 2713 |
| 2702 // Handle store cache miss. | 2714 // Handle store cache miss. |
| 2703 __ bind(&miss); | 2715 __ bind(&miss); |
| 2704 TailCallBuiltin(masm(), MissBuiltin(kind())); | 2716 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 2705 | 2717 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2765 | 2777 |
| 2766 // Perform global security token check if needed. | 2778 // Perform global security token check if needed. |
| 2767 if (object->IsJSGlobalProxy()) { | 2779 if (object->IsJSGlobalProxy()) { |
| 2768 __ CheckAccessGlobalProxy(receiver(), scratch1(), &miss); | 2780 __ CheckAccessGlobalProxy(receiver(), scratch1(), &miss); |
| 2769 } | 2781 } |
| 2770 | 2782 |
| 2771 // Stub never generated for non-global objects that require access | 2783 // Stub never generated for non-global objects that require access |
| 2772 // checks. | 2784 // checks. |
| 2773 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 2785 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 2774 | 2786 |
| 2775 __ pop(scratch1()); // remove the return address | 2787 __k pop(scratch1()); // remove the return address |
| 2776 __ push(receiver()); | 2788 __ push(receiver()); |
| 2777 __ push(this->name()); | 2789 __ push(this->name()); |
| 2778 __ push(value()); | 2790 __ push(value()); |
| 2779 __ Push(Smi::FromInt(strict_mode())); | 2791 __ Push(Smi::FromInt(strict_mode())); |
| 2780 __ push(scratch1()); // restore return address | 2792 __k push(scratch1()); // restore return address |
| 2781 | 2793 |
| 2782 // Do tail-call to the runtime system. | 2794 // Do tail-call to the runtime system. |
| 2783 ExternalReference store_ic_property = | 2795 ExternalReference store_ic_property = |
| 2784 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); | 2796 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); |
| 2785 __ TailCallExternalReference(store_ic_property, 4, 1); | 2797 __ TailCallExternalReference(store_ic_property, 4, 1); |
| 2786 | 2798 |
| 2787 // Handle store cache miss. | 2799 // Handle store cache miss. |
| 2788 __ bind(&miss); | 2800 __ bind(&miss); |
| 2789 TailCallBuiltin(masm(), MissBuiltin(kind())); | 2801 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 2790 | 2802 |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3110 __ CheckMap(key, | 3122 __ CheckMap(key, |
| 3111 masm->isolate()->factory()->heap_number_map(), | 3123 masm->isolate()->factory()->heap_number_map(), |
| 3112 fail, | 3124 fail, |
| 3113 DONT_DO_SMI_CHECK); | 3125 DONT_DO_SMI_CHECK); |
| 3114 __ movsd(xmm_scratch0, FieldOperand(key, HeapNumber::kValueOffset)); | 3126 __ movsd(xmm_scratch0, FieldOperand(key, HeapNumber::kValueOffset)); |
| 3115 __ cvttsd2si(scratch, xmm_scratch0); | 3127 __ cvttsd2si(scratch, xmm_scratch0); |
| 3116 __ cvtlsi2sd(xmm_scratch1, scratch); | 3128 __ cvtlsi2sd(xmm_scratch1, scratch); |
| 3117 __ ucomisd(xmm_scratch1, xmm_scratch0); | 3129 __ ucomisd(xmm_scratch1, xmm_scratch0); |
| 3118 __ j(not_equal, fail); | 3130 __ j(not_equal, fail); |
| 3119 __ j(parity_even, fail); // NaN. | 3131 __ j(parity_even, fail); // NaN. |
| 3132 #ifdef V8_TARGET_ARCH_X32 |
| 3133 __ cmpl(scratch, Immediate(0xc0000000)); |
| 3134 __ j(sign, fail); |
| 3135 #endif |
| 3120 __ Integer32ToSmi(key, scratch); | 3136 __ Integer32ToSmi(key, scratch); |
| 3121 __ bind(&key_ok); | 3137 __ bind(&key_ok); |
| 3122 } | 3138 } |
| 3123 | 3139 |
| 3124 | 3140 |
| 3125 void KeyedStoreStubCompiler::GenerateStoreExternalArray( | 3141 void KeyedStoreStubCompiler::GenerateStoreExternalArray( |
| 3126 MacroAssembler* masm, | 3142 MacroAssembler* masm, |
| 3127 ElementsKind elements_kind) { | 3143 ElementsKind elements_kind) { |
| 3128 // ----------- S t a t e ------------- | 3144 // ----------- S t a t e ------------- |
| 3129 // -- rax : value | 3145 // -- rax : value |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3238 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | 3254 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
| 3239 __ movsd(Operand(rbx, rdi, times_8, 0), xmm0); | 3255 __ movsd(Operand(rbx, rdi, times_8, 0), xmm0); |
| 3240 __ ret(0); | 3256 __ ret(0); |
| 3241 } else { | 3257 } else { |
| 3242 // Perform float-to-int conversion with truncation (round-to-zero) | 3258 // Perform float-to-int conversion with truncation (round-to-zero) |
| 3243 // behavior. | 3259 // behavior. |
| 3244 // Fast path: use machine instruction to convert to int64. If that | 3260 // Fast path: use machine instruction to convert to int64. If that |
| 3245 // fails (out-of-range), go into the runtime. | 3261 // fails (out-of-range), go into the runtime. |
| 3246 __ cvttsd2siq(r8, xmm0); | 3262 __ cvttsd2siq(r8, xmm0); |
| 3247 __ Set(kScratchRegister, V8_UINT64_C(0x8000000000000000)); | 3263 __ Set(kScratchRegister, V8_UINT64_C(0x8000000000000000)); |
| 3248 __ cmpq(r8, kScratchRegister); | 3264 __k cmpq(r8, kScratchRegister); |
| 3249 __ j(equal, &slow); | 3265 __ j(equal, &slow); |
| 3250 | 3266 |
| 3251 // rdx: value (converted to an untagged integer) | 3267 // rdx: value (converted to an untagged integer) |
| 3252 // rdi: untagged index | 3268 // rdi: untagged index |
| 3253 // rbx: base pointer of external storage | 3269 // rbx: base pointer of external storage |
| 3254 switch (elements_kind) { | 3270 switch (elements_kind) { |
| 3255 case EXTERNAL_BYTE_ELEMENTS: | 3271 case EXTERNAL_BYTE_ELEMENTS: |
| 3256 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 3272 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3257 __ movb(Operand(rbx, rdi, times_1, 0), r8); | 3273 __ movb(Operand(rbx, rdi, times_1, 0), r8); |
| 3258 break; | 3274 break; |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3533 __ Move(FieldOperand(rdi, JSObject::kMapOffset), | 3549 __ Move(FieldOperand(rdi, JSObject::kMapOffset), |
| 3534 masm->isolate()->factory()->fixed_double_array_map()); | 3550 masm->isolate()->factory()->fixed_double_array_map()); |
| 3535 __ Move(FieldOperand(rdi, FixedDoubleArray::kLengthOffset), | 3551 __ Move(FieldOperand(rdi, FixedDoubleArray::kLengthOffset), |
| 3536 Smi::FromInt(JSArray::kPreallocatedArrayElements)); | 3552 Smi::FromInt(JSArray::kPreallocatedArrayElements)); |
| 3537 | 3553 |
| 3538 // Increment the length of the array. | 3554 // Increment the length of the array. |
| 3539 __ SmiToInteger32(rcx, rcx); | 3555 __ SmiToInteger32(rcx, rcx); |
| 3540 __ StoreNumberToDoubleElements(rax, rdi, rcx, xmm0, | 3556 __ StoreNumberToDoubleElements(rax, rdi, rcx, xmm0, |
| 3541 &restore_key_transition_elements_kind); | 3557 &restore_key_transition_elements_kind); |
| 3542 | 3558 |
| 3543 __ movq(r8, BitCast<int64_t, uint64_t>(kHoleNanInt64), RelocInfo::NONE64); | 3559 __k movq(r8, BitCast<int64_t, uint64_t>(kHoleNanInt64), RelocInfo::NONE64); |
| 3544 for (int i = 1; i < JSArray::kPreallocatedArrayElements; i++) { | 3560 for (int i = 1; i < JSArray::kPreallocatedArrayElements; i++) { |
| 3545 __ movq(FieldOperand(rdi, FixedDoubleArray::OffsetOfElementAt(i)), r8); | 3561 __k movq(FieldOperand(rdi, FixedDoubleArray::OffsetOfElementAt(i)), r8); |
| 3546 } | 3562 } |
| 3547 | 3563 |
| 3548 // Install the new backing store in the JSArray. | 3564 // Install the new backing store in the JSArray. |
| 3549 __ movq(FieldOperand(rdx, JSObject::kElementsOffset), rdi); | 3565 __ movq(FieldOperand(rdx, JSObject::kElementsOffset), rdi); |
| 3550 __ RecordWriteField(rdx, JSObject::kElementsOffset, rdi, rbx, | 3566 __ RecordWriteField(rdx, JSObject::kElementsOffset, rdi, rbx, |
| 3551 kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | 3567 kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
| 3552 | 3568 |
| 3553 // Increment the length of the array. | 3569 // Increment the length of the array. |
| 3554 __ Move(FieldOperand(rdx, JSArray::kLengthOffset), Smi::FromInt(1)); | 3570 __ Move(FieldOperand(rdx, JSArray::kLengthOffset), Smi::FromInt(1)); |
| 3555 __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset)); | 3571 __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset)); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3567 // Grow the array and finish the store. | 3583 // Grow the array and finish the store. |
| 3568 __ SmiAddConstant(FieldOperand(rdx, JSArray::kLengthOffset), | 3584 __ SmiAddConstant(FieldOperand(rdx, JSArray::kLengthOffset), |
| 3569 Smi::FromInt(1)); | 3585 Smi::FromInt(1)); |
| 3570 __ jmp(&finish_store); | 3586 __ jmp(&finish_store); |
| 3571 | 3587 |
| 3572 __ bind(&slow); | 3588 __ bind(&slow); |
| 3573 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); | 3589 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); |
| 3574 } | 3590 } |
| 3575 } | 3591 } |
| 3576 | 3592 |
| 3577 | 3593 #undef __a |
| 3594 #undef __k |
| 3578 #undef __ | 3595 #undef __ |
| 3579 | 3596 |
| 3580 } } // namespace v8::internal | 3597 } } // namespace v8::internal |
| 3581 | 3598 |
| 3582 #endif // V8_TARGET_ARCH_X64 | 3599 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |