| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 209 for (int i = 0; i < num_parameters; i++) { | 209 for (int i = 0; i < num_parameters; i++) { |
| 210 Variable* var = scope()->parameter(i); | 210 Variable* var = scope()->parameter(i); |
| 211 if (var->IsContextSlot()) { | 211 if (var->IsContextSlot()) { |
| 212 int parameter_offset = StandardFrameConstants::kCallerSPOffset + | 212 int parameter_offset = StandardFrameConstants::kCallerSPOffset + |
| 213 (num_parameters - 1 - i) * kPointerSize; | 213 (num_parameters - 1 - i) * kPointerSize; |
| 214 // Load parameter from stack. | 214 // Load parameter from stack. |
| 215 __ movq(rax, Operand(rbp, parameter_offset)); | 215 __ movq(rax, Operand(rbp, parameter_offset)); |
| 216 // Store it in the context. | 216 // Store it in the context. |
| 217 int context_offset = Context::SlotOffset(var->index()); | 217 int context_offset = Context::SlotOffset(var->index()); |
| 218 __ movq(Operand(rsi, context_offset), rax); | 218 __ movq(Operand(rsi, context_offset), rax); |
| 219 // Update the write barrier. This clobbers all involved | 219 // Update the write barrier. |
| 220 // registers, so we have use a third register to avoid | 220 __ RecordWrite(rsi, context_offset, rax, rbx); |
| 221 // clobbering rsi. | |
| 222 __ movq(rcx, rsi); | |
| 223 __ RecordWrite(rcx, context_offset, rax, rbx); | |
| 224 } | 221 } |
| 225 } | 222 } |
| 226 Comment(";;; End allocate local context"); | 223 Comment(";;; End allocate local context"); |
| 227 } | 224 } |
| 228 | 225 |
| 229 // Trace the call. | 226 // Trace the call. |
| 230 if (FLAG_trace) { | 227 if (FLAG_trace) { |
| 231 __ CallRuntime(Runtime::kTraceEnter, 0); | 228 __ CallRuntime(Runtime::kTraceEnter, 0); |
| 232 } | 229 } |
| 233 return !is_aborted(); | 230 return !is_aborted(); |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 504 LPointerMap* pointers = instr->pointer_map(); | 501 LPointerMap* pointers = instr->pointer_map(); |
| 505 RecordPosition(pointers->position()); | 502 RecordPosition(pointers->position()); |
| 506 | 503 |
| 507 __ CallRuntime(function, num_arguments); | 504 __ CallRuntime(function, num_arguments); |
| 508 RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT, 0); | 505 RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT, 0); |
| 509 } | 506 } |
| 510 | 507 |
| 511 | 508 |
| 512 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, | 509 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, |
| 513 int argc, | 510 int argc, |
| 514 LInstruction* instr) { | 511 LInstruction* instr, |
| 515 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 512 LOperand* context) { |
| 513 ASSERT(context->IsRegister() || context->IsStackSlot()); |
| 514 if (context->IsRegister()) { |
| 515 if (!ToRegister(context).is(rsi)) { |
| 516 __ movq(rsi, ToRegister(context)); |
| 517 } |
| 518 } else { |
| 519 // Context is stack slot. |
| 520 __ movq(rsi, ToOperand(context)); |
| 521 } |
| 522 |
| 516 __ CallRuntimeSaveDoubles(id); | 523 __ CallRuntimeSaveDoubles(id); |
| 517 RecordSafepointWithRegisters( | 524 RecordSafepointWithRegisters( |
| 518 instr->pointer_map(), argc, Safepoint::kNoDeoptimizationIndex); | 525 instr->pointer_map(), argc, Safepoint::kNoDeoptimizationIndex); |
| 519 } | 526 } |
| 520 | 527 |
| 521 | 528 |
| 522 void LCodeGen::RegisterLazyDeoptimization(LInstruction* instr, | 529 void LCodeGen::RegisterLazyDeoptimization(LInstruction* instr, |
| 523 SafepointMode safepoint_mode, | 530 SafepointMode safepoint_mode, |
| 524 int argc) { | 531 int argc) { |
| 525 // Create the environment to bailout to. If the call has side effects | 532 // Create the environment to bailout to. If the call has side effects |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 671 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), | 678 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), |
| 672 kind, arguments, deoptimization_index); | 679 kind, arguments, deoptimization_index); |
| 673 for (int i = 0; i < operands->length(); i++) { | 680 for (int i = 0; i < operands->length(); i++) { |
| 674 LOperand* pointer = operands->at(i); | 681 LOperand* pointer = operands->at(i); |
| 675 if (pointer->IsStackSlot()) { | 682 if (pointer->IsStackSlot()) { |
| 676 safepoint.DefinePointerSlot(pointer->index()); | 683 safepoint.DefinePointerSlot(pointer->index()); |
| 677 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { | 684 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { |
| 678 safepoint.DefinePointerRegister(ToRegister(pointer)); | 685 safepoint.DefinePointerRegister(ToRegister(pointer)); |
| 679 } | 686 } |
| 680 } | 687 } |
| 681 if (kind & Safepoint::kWithRegisters) { | |
| 682 // Register rsi always contains a pointer to the context. | |
| 683 safepoint.DefinePointerRegister(rsi); | |
| 684 } | |
| 685 } | 688 } |
| 686 | 689 |
| 687 | 690 |
| 688 void LCodeGen::RecordSafepoint(LPointerMap* pointers, | 691 void LCodeGen::RecordSafepoint(LPointerMap* pointers, |
| 689 int deoptimization_index) { | 692 int deoptimization_index) { |
| 690 RecordSafepoint(pointers, Safepoint::kSimple, 0, deoptimization_index); | 693 RecordSafepoint(pointers, Safepoint::kSimple, 0, deoptimization_index); |
| 691 } | 694 } |
| 692 | 695 |
| 693 | 696 |
| 694 void LCodeGen::RecordSafepoint(int deoptimization_index) { | 697 void LCodeGen::RecordSafepoint(int deoptimization_index) { |
| (...skipping 560 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1255 | 1258 |
| 1256 | 1259 |
| 1257 void LCodeGen::DoBitNotI(LBitNotI* instr) { | 1260 void LCodeGen::DoBitNotI(LBitNotI* instr) { |
| 1258 LOperand* input = instr->InputAt(0); | 1261 LOperand* input = instr->InputAt(0); |
| 1259 ASSERT(input->Equals(instr->result())); | 1262 ASSERT(input->Equals(instr->result())); |
| 1260 __ not_(ToRegister(input)); | 1263 __ not_(ToRegister(input)); |
| 1261 } | 1264 } |
| 1262 | 1265 |
| 1263 | 1266 |
| 1264 void LCodeGen::DoThrow(LThrow* instr) { | 1267 void LCodeGen::DoThrow(LThrow* instr) { |
| 1265 __ push(ToRegister(instr->InputAt(0))); | 1268 __ push(ToRegister(instr->value())); |
| 1266 CallRuntime(Runtime::kThrow, 1, instr); | 1269 CallRuntime(Runtime::kThrow, 1, instr); |
| 1267 | 1270 |
| 1268 if (FLAG_debug_code) { | 1271 if (FLAG_debug_code) { |
| 1269 Comment("Unreachable code."); | 1272 Comment("Unreachable code."); |
| 1270 __ int3(); | 1273 __ int3(); |
| 1271 } | 1274 } |
| 1272 } | 1275 } |
| 1273 | 1276 |
| 1274 | 1277 |
| 1275 void LCodeGen::DoAddI(LAddI* instr) { | 1278 void LCodeGen::DoAddI(LAddI* instr) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1311 case Token::DIV: | 1314 case Token::DIV: |
| 1312 __ divsd(left, right); | 1315 __ divsd(left, right); |
| 1313 break; | 1316 break; |
| 1314 case Token::MOD: | 1317 case Token::MOD: |
| 1315 __ PrepareCallCFunction(2); | 1318 __ PrepareCallCFunction(2); |
| 1316 __ movaps(xmm0, left); | 1319 __ movaps(xmm0, left); |
| 1317 ASSERT(right.is(xmm1)); | 1320 ASSERT(right.is(xmm1)); |
| 1318 __ CallCFunction( | 1321 __ CallCFunction( |
| 1319 ExternalReference::double_fp_operation(Token::MOD, isolate()), 2); | 1322 ExternalReference::double_fp_operation(Token::MOD, isolate()), 2); |
| 1320 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1323 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 1324 __ movq(rsi, Immediate(0)); |
| 1321 __ movaps(result, xmm0); | 1325 __ movaps(result, xmm0); |
| 1322 break; | 1326 break; |
| 1323 default: | 1327 default: |
| 1324 UNREACHABLE(); | 1328 UNREACHABLE(); |
| 1325 break; | 1329 break; |
| 1326 } | 1330 } |
| 1327 } | 1331 } |
| 1328 | 1332 |
| 1329 | 1333 |
| 1330 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 1334 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
| 1331 ASSERT(ToRegister(instr->InputAt(0)).is(rdx)); | 1335 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 1332 ASSERT(ToRegister(instr->InputAt(1)).is(rax)); | 1336 ASSERT(ToRegister(instr->left()).is(rdx)); |
| 1337 ASSERT(ToRegister(instr->right()).is(rax)); |
| 1333 ASSERT(ToRegister(instr->result()).is(rax)); | 1338 ASSERT(ToRegister(instr->result()).is(rax)); |
| 1334 | 1339 |
| 1335 BinaryOpStub stub(instr->op(), NO_OVERWRITE); | 1340 BinaryOpStub stub(instr->op(), NO_OVERWRITE); |
| 1336 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 1341 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 1337 __ nop(); // Signals no inlined code. | 1342 __ nop(); // Signals no inlined code. |
| 1338 } | 1343 } |
| 1339 | 1344 |
| 1340 | 1345 |
| 1341 int LCodeGen::GetNextEmittedBlock(int block) { | 1346 int LCodeGen::GetNextEmittedBlock(int block) { |
| 1342 for (int i = block + 1; i < graph()->blocks()->length(); ++i) { | 1347 for (int i = block + 1; i < graph()->blocks()->length(); ++i) { |
| (...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1822 int true_block = instr->true_block_id(); | 1827 int true_block = instr->true_block_id(); |
| 1823 int false_block = instr->false_block_id(); | 1828 int false_block = instr->false_block_id(); |
| 1824 | 1829 |
| 1825 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); | 1830 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); |
| 1826 EmitBranch(true_block, false_block, equal); | 1831 EmitBranch(true_block, false_block, equal); |
| 1827 } | 1832 } |
| 1828 | 1833 |
| 1829 | 1834 |
| 1830 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 1835 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
| 1831 InstanceofStub stub(InstanceofStub::kNoFlags); | 1836 InstanceofStub stub(InstanceofStub::kNoFlags); |
| 1832 __ push(ToRegister(instr->InputAt(0))); | 1837 __ push(ToRegister(instr->left())); |
| 1833 __ push(ToRegister(instr->InputAt(1))); | 1838 __ push(ToRegister(instr->right())); |
| 1834 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 1839 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 1835 Label true_value, done; | 1840 Label true_value, done; |
| 1836 __ testq(rax, rax); | 1841 __ testq(rax, rax); |
| 1837 __ j(zero, &true_value, Label::kNear); | 1842 __ j(zero, &true_value, Label::kNear); |
| 1838 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); | 1843 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); |
| 1839 __ jmp(&done, Label::kNear); | 1844 __ jmp(&done, Label::kNear); |
| 1840 __ bind(&true_value); | 1845 __ bind(&true_value); |
| 1841 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); | 1846 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); |
| 1842 __ bind(&done); | 1847 __ bind(&done); |
| 1843 } | 1848 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1858 private: | 1863 private: |
| 1859 LInstanceOfKnownGlobal* instr_; | 1864 LInstanceOfKnownGlobal* instr_; |
| 1860 Label map_check_; | 1865 Label map_check_; |
| 1861 }; | 1866 }; |
| 1862 | 1867 |
| 1863 | 1868 |
| 1864 DeferredInstanceOfKnownGlobal* deferred; | 1869 DeferredInstanceOfKnownGlobal* deferred; |
| 1865 deferred = new DeferredInstanceOfKnownGlobal(this, instr); | 1870 deferred = new DeferredInstanceOfKnownGlobal(this, instr); |
| 1866 | 1871 |
| 1867 Label done, false_result; | 1872 Label done, false_result; |
| 1868 Register object = ToRegister(instr->InputAt(0)); | 1873 Register object = ToRegister(instr->value()); |
| 1869 | 1874 |
| 1870 // A Smi is not an instance of anything. | 1875 // A Smi is not an instance of anything. |
| 1871 __ JumpIfSmi(object, &false_result); | 1876 __ JumpIfSmi(object, &false_result); |
| 1872 | 1877 |
| 1873 // This is the inlined call site instanceof cache. The two occurences of the | 1878 // This is the inlined call site instanceof cache. The two occurences of the |
| 1874 // hole value will be patched to the last map/result pair generated by the | 1879 // hole value will be patched to the last map/result pair generated by the |
| 1875 // instanceof stub. | 1880 // instanceof stub. |
| 1876 Label cache_miss; | 1881 Label cache_miss; |
| 1877 // Use a temp register to avoid memory operands with variable lengths. | 1882 // Use a temp register to avoid memory operands with variable lengths. |
| 1878 Register map = ToRegister(instr->TempAt(0)); | 1883 Register map = ToRegister(instr->TempAt(0)); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1910 | 1915 |
| 1911 | 1916 |
| 1912 void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, | 1917 void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, |
| 1913 Label* map_check) { | 1918 Label* map_check) { |
| 1914 { | 1919 { |
| 1915 PushSafepointRegistersScope scope(this); | 1920 PushSafepointRegistersScope scope(this); |
| 1916 InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>( | 1921 InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>( |
| 1917 InstanceofStub::kNoFlags | InstanceofStub::kCallSiteInlineCheck); | 1922 InstanceofStub::kNoFlags | InstanceofStub::kCallSiteInlineCheck); |
| 1918 InstanceofStub stub(flags); | 1923 InstanceofStub stub(flags); |
| 1919 | 1924 |
| 1920 __ push(ToRegister(instr->InputAt(0))); | 1925 __ push(ToRegister(instr->value())); |
| 1921 __ Push(instr->function()); | 1926 __ Push(instr->function()); |
| 1922 | 1927 |
| 1923 static const int kAdditionalDelta = 10; | 1928 static const int kAdditionalDelta = 10; |
| 1924 int delta = | 1929 int delta = |
| 1925 masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; | 1930 masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; |
| 1926 ASSERT(delta >= 0); | 1931 ASSERT(delta >= 0); |
| 1927 __ push_imm32(delta); | 1932 __ push_imm32(delta); |
| 1928 | 1933 |
| 1929 // We are pushing three values on the stack but recording a | 1934 // We are pushing three values on the stack but recording a |
| 1930 // safepoint with two arguments because stub is going to | 1935 // safepoint with two arguments because stub is going to |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1946 __ j(not_zero, &load_false); | 1951 __ j(not_zero, &load_false); |
| 1947 __ LoadRoot(rax, Heap::kTrueValueRootIndex); | 1952 __ LoadRoot(rax, Heap::kTrueValueRootIndex); |
| 1948 __ jmp(&done); | 1953 __ jmp(&done); |
| 1949 __ bind(&load_false); | 1954 __ bind(&load_false); |
| 1950 __ LoadRoot(rax, Heap::kFalseValueRootIndex); | 1955 __ LoadRoot(rax, Heap::kFalseValueRootIndex); |
| 1951 __ bind(&done); | 1956 __ bind(&done); |
| 1952 } | 1957 } |
| 1953 | 1958 |
| 1954 | 1959 |
| 1955 void LCodeGen::DoCmpT(LCmpT* instr) { | 1960 void LCodeGen::DoCmpT(LCmpT* instr) { |
| 1961 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 1962 ASSERT((ToRegister(instr->left()).is(rax) && |
| 1963 ToRegister(instr->right()).is(rdx)) || |
| 1964 (ToRegister(instr->left()).is(rdx) && |
| 1965 ToRegister(instr->right()).is(rax))); |
| 1966 ASSERT(ToRegister(instr->result()).is(rax)); |
| 1956 Token::Value op = instr->op(); | 1967 Token::Value op = instr->op(); |
| 1957 | 1968 |
| 1958 Handle<Code> ic = CompareIC::GetUninitialized(op); | 1969 Handle<Code> ic = CompareIC::GetUninitialized(op); |
| 1959 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 1970 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 1960 | 1971 |
| 1961 Condition condition = TokenToCondition(op, false); | 1972 Condition condition = TokenToCondition(op, false); |
| 1962 if (op == Token::GT || op == Token::LTE) { | 1973 if (op == Token::GT || op == Token::LTE) { |
| 1963 condition = ReverseCondition(condition); | 1974 condition = ReverseCondition(condition); |
| 1964 } | 1975 } |
| 1965 Label true_value, done; | 1976 Label true_value, done; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1996 __ movq(result, Operand(result, 0)); | 2007 __ movq(result, Operand(result, 0)); |
| 1997 } | 2008 } |
| 1998 if (instr->hydrogen()->check_hole_value()) { | 2009 if (instr->hydrogen()->check_hole_value()) { |
| 1999 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); | 2010 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); |
| 2000 DeoptimizeIf(equal, instr->environment()); | 2011 DeoptimizeIf(equal, instr->environment()); |
| 2001 } | 2012 } |
| 2002 } | 2013 } |
| 2003 | 2014 |
| 2004 | 2015 |
| 2005 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { | 2016 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { |
| 2017 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 2006 ASSERT(ToRegister(instr->global_object()).is(rax)); | 2018 ASSERT(ToRegister(instr->global_object()).is(rax)); |
| 2007 ASSERT(ToRegister(instr->result()).is(rax)); | 2019 ASSERT(ToRegister(instr->result()).is(rax)); |
| 2008 | 2020 |
| 2009 __ Move(rcx, instr->name()); | 2021 __ Move(rcx, instr->name()); |
| 2010 RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET : | 2022 RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET : |
| 2011 RelocInfo::CODE_TARGET_CONTEXT; | 2023 RelocInfo::CODE_TARGET_CONTEXT; |
| 2012 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2024 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| 2013 CallCode(ic, mode, instr); | 2025 CallCode(ic, mode, instr); |
| 2014 } | 2026 } |
| 2015 | 2027 |
| 2016 | 2028 |
| 2017 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { | 2029 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { |
| 2018 Register value = ToRegister(instr->InputAt(0)); | 2030 Register value = ToRegister(instr->value()); |
| 2019 Register temp = ToRegister(instr->TempAt(0)); | 2031 Register temp = ToRegister(instr->TempAt(0)); |
| 2020 ASSERT(!value.is(temp)); | 2032 ASSERT(!value.is(temp)); |
| 2021 bool check_hole = instr->hydrogen()->check_hole_value(); | 2033 bool check_hole = instr->hydrogen()->check_hole_value(); |
| 2022 if (!check_hole && value.is(rax)) { | 2034 if (!check_hole && value.is(rax)) { |
| 2023 __ store_rax(instr->hydrogen()->cell().location(), | 2035 __ store_rax(instr->hydrogen()->cell().location(), |
| 2024 RelocInfo::GLOBAL_PROPERTY_CELL); | 2036 RelocInfo::GLOBAL_PROPERTY_CELL); |
| 2025 return; | 2037 return; |
| 2026 } | 2038 } |
| 2027 // If the cell we are storing to contains the hole it could have | 2039 // If the cell we are storing to contains the hole it could have |
| 2028 // been deleted from the property dictionary. In that case, we need | 2040 // been deleted from the property dictionary. In that case, we need |
| (...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2471 Condition is_smi = __ CheckSmi(receiver); | 2483 Condition is_smi = __ CheckSmi(receiver); |
| 2472 DeoptimizeIf(is_smi, instr->environment()); | 2484 DeoptimizeIf(is_smi, instr->environment()); |
| 2473 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister); | 2485 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister); |
| 2474 DeoptimizeIf(below, instr->environment()); | 2486 DeoptimizeIf(below, instr->environment()); |
| 2475 __ jmp(&receiver_ok, Label::kNear); | 2487 __ jmp(&receiver_ok, Label::kNear); |
| 2476 | 2488 |
| 2477 __ bind(&global_object); | 2489 __ bind(&global_object); |
| 2478 // TODO(kmillikin): We have a hydrogen value for the global object. See | 2490 // TODO(kmillikin): We have a hydrogen value for the global object. See |
| 2479 // if it's better to use it than to explicitly fetch it from the context | 2491 // if it's better to use it than to explicitly fetch it from the context |
| 2480 // here. | 2492 // here. |
| 2481 __ movq(receiver, ContextOperand(rsi, Context::GLOBAL_INDEX)); | 2493 __ movq(receiver, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 2494 __ movq(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX)); |
| 2482 __ movq(receiver, | 2495 __ movq(receiver, |
| 2483 FieldOperand(receiver, JSGlobalObject::kGlobalReceiverOffset)); | 2496 FieldOperand(receiver, JSGlobalObject::kGlobalReceiverOffset)); |
| 2484 __ bind(&receiver_ok); | 2497 __ bind(&receiver_ok); |
| 2485 | 2498 |
| 2486 // Copy the arguments to this function possibly from the | 2499 // Copy the arguments to this function possibly from the |
| 2487 // adaptor frame below it. | 2500 // adaptor frame below it. |
| 2488 const uint32_t kArgumentsLimit = 1 * KB; | 2501 const uint32_t kArgumentsLimit = 1 * KB; |
| 2489 __ cmpq(length, Immediate(kArgumentsLimit)); | 2502 __ cmpq(length, Immediate(kArgumentsLimit)); |
| 2490 DeoptimizeIf(above, instr->environment()); | 2503 DeoptimizeIf(above, instr->environment()); |
| 2491 | 2504 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2510 LEnvironment* env = instr->deoptimization_environment(); | 2523 LEnvironment* env = instr->deoptimization_environment(); |
| 2511 RecordPosition(pointers->position()); | 2524 RecordPosition(pointers->position()); |
| 2512 RegisterEnvironmentForDeoptimization(env); | 2525 RegisterEnvironmentForDeoptimization(env); |
| 2513 SafepointGenerator safepoint_generator(this, | 2526 SafepointGenerator safepoint_generator(this, |
| 2514 pointers, | 2527 pointers, |
| 2515 env->deoptimization_index()); | 2528 env->deoptimization_index()); |
| 2516 v8::internal::ParameterCount actual(rax); | 2529 v8::internal::ParameterCount actual(rax); |
| 2517 __ InvokeFunction(function, actual, CALL_FUNCTION, | 2530 __ InvokeFunction(function, actual, CALL_FUNCTION, |
| 2518 safepoint_generator, CALL_AS_METHOD); | 2531 safepoint_generator, CALL_AS_METHOD); |
| 2519 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2532 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 2533 __ movq(rsi, Immediate(0)); |
| 2520 } | 2534 } |
| 2521 | 2535 |
| 2522 | 2536 |
| 2523 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 2537 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
| 2524 LOperand* argument = instr->InputAt(0); | 2538 LOperand* argument = instr->InputAt(0); |
| 2525 EmitPushTaggedOperand(argument); | 2539 EmitPushTaggedOperand(argument); |
| 2526 } | 2540 } |
| 2527 | 2541 |
| 2528 | 2542 |
| 2529 void LCodeGen::DoThisFunction(LThisFunction* instr) { | 2543 void LCodeGen::DoThisFunction(LThisFunction* instr) { |
| 2530 Register result = ToRegister(instr->result()); | 2544 Register result = ToRegister(instr->result()); |
| 2531 __ movq(result, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 2545 __ movq(result, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
| 2532 } | 2546 } |
| 2533 | 2547 |
| 2534 | 2548 |
| 2535 void LCodeGen::DoContext(LContext* instr) { | 2549 void LCodeGen::DoContext(LContext* instr) { |
| 2536 Register result = ToRegister(instr->result()); | 2550 Register result = ToRegister(instr->result()); |
| 2537 __ movq(result, rsi); | 2551 __ movq(result, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 2538 } | 2552 } |
| 2539 | 2553 |
| 2540 | 2554 |
| 2541 void LCodeGen::DoOuterContext(LOuterContext* instr) { | 2555 void LCodeGen::DoOuterContext(LOuterContext* instr) { |
| 2542 Register context = ToRegister(instr->context()); | 2556 Register context = ToRegister(instr->context()); |
| 2543 Register result = ToRegister(instr->result()); | 2557 Register result = ToRegister(instr->result()); |
| 2544 __ movq(result, | 2558 __ movq(result, |
| 2545 Operand(context, Context::SlotOffset(Context::PREVIOUS_INDEX))); | 2559 Operand(context, Context::SlotOffset(Context::PREVIOUS_INDEX))); |
| 2546 } | 2560 } |
| 2547 | 2561 |
| 2548 | 2562 |
| 2549 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { | 2563 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { |
| 2564 Register context = ToRegister(instr->context()); |
| 2550 Register result = ToRegister(instr->result()); | 2565 Register result = ToRegister(instr->result()); |
| 2551 __ movq(result, GlobalObjectOperand()); | 2566 __ movq(result, |
| 2567 Operand(context, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 2552 } | 2568 } |
| 2553 | 2569 |
| 2554 | 2570 |
| 2555 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { | 2571 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { |
| 2556 Register global = ToRegister(instr->global()); | 2572 Register global = ToRegister(instr->global()); |
| 2557 Register result = ToRegister(instr->result()); | 2573 Register result = ToRegister(instr->result()); |
| 2558 __ movq(result, FieldOperand(global, GlobalObject::kGlobalReceiverOffset)); | 2574 __ movq(result, FieldOperand(global, GlobalObject::kGlobalReceiverOffset)); |
| 2559 } | 2575 } |
| 2560 | 2576 |
| 2561 | 2577 |
| 2562 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, | 2578 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, |
| 2563 int arity, | 2579 int arity, |
| 2564 LInstruction* instr, | 2580 LInstruction* instr, |
| 2565 CallKind call_kind) { | 2581 CallKind call_kind) { |
| 2566 // Change context if needed. | 2582 // Change context if needed. |
| 2567 bool change_context = | 2583 bool change_context = |
| 2568 (info()->closure()->context() != function->context()) || | 2584 (info()->closure()->context() != function->context()) || |
| 2569 scope()->contains_with() || | 2585 scope()->contains_with() || |
| 2570 (scope()->num_heap_slots() > 0); | 2586 (scope()->num_heap_slots() > 0); |
| 2571 if (change_context) { | 2587 if (change_context) { |
| 2572 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | 2588 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
| 2589 } else { |
| 2590 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 2573 } | 2591 } |
| 2574 | 2592 |
| 2575 // Set rax to arguments count if adaption is not needed. Assumes that rax | 2593 // Set rax to arguments count if adaption is not needed. Assumes that rax |
| 2576 // is available to write to at this point. | 2594 // is available to write to at this point. |
| 2577 if (!function->NeedsArgumentsAdaption()) { | 2595 if (!function->NeedsArgumentsAdaption()) { |
| 2578 __ Set(rax, arity); | 2596 __ Set(rax, arity); |
| 2579 } | 2597 } |
| 2580 | 2598 |
| 2581 LPointerMap* pointers = instr->pointer_map(); | 2599 LPointerMap* pointers = instr->pointer_map(); |
| 2582 RecordPosition(pointers->position()); | 2600 RecordPosition(pointers->position()); |
| 2583 | 2601 |
| 2584 // Invoke function. | 2602 // Invoke function. |
| 2585 __ SetCallKind(rcx, call_kind); | 2603 __ SetCallKind(rcx, call_kind); |
| 2586 if (*function == *info()->closure()) { | 2604 if (*function == *info()->closure()) { |
| 2587 __ CallSelf(); | 2605 __ CallSelf(); |
| 2588 } else { | 2606 } else { |
| 2589 __ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset)); | 2607 __ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset)); |
| 2590 } | 2608 } |
| 2591 | 2609 |
| 2592 // Setup deoptimization. | 2610 // Setup deoptimization. |
| 2593 RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT, 0); | 2611 RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT, 0); |
| 2594 | 2612 |
| 2595 // Restore context. | 2613 // Restore context. |
| 2596 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2614 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 2615 __ movq(rsi, Immediate(0)); |
| 2597 } | 2616 } |
| 2598 | 2617 |
| 2599 | 2618 |
| 2600 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 2619 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |
| 2601 ASSERT(ToRegister(instr->result()).is(rax)); | 2620 ASSERT(ToRegister(instr->result()).is(rax)); |
| 2602 __ Move(rdi, instr->function()); | 2621 __ Move(rdi, instr->function()); |
| 2603 CallKnownFunction(instr->function(), | 2622 CallKnownFunction(instr->function(), |
| 2604 instr->arity(), | 2623 instr->arity(), |
| 2605 instr, | 2624 instr, |
| 2606 CALL_AS_METHOD); | 2625 CALL_AS_METHOD); |
| 2607 } | 2626 } |
| 2608 | 2627 |
| 2609 | 2628 |
| 2610 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { | 2629 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { |
| 2611 Register input_reg = ToRegister(instr->InputAt(0)); | 2630 Register input_reg = ToRegister(instr->value()); |
| 2612 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), | 2631 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 2613 Heap::kHeapNumberMapRootIndex); | 2632 Heap::kHeapNumberMapRootIndex); |
| 2614 DeoptimizeIf(not_equal, instr->environment()); | 2633 DeoptimizeIf(not_equal, instr->environment()); |
| 2615 | 2634 |
| 2616 Label done; | 2635 Label done; |
| 2617 Register tmp = input_reg.is(rax) ? rcx : rax; | 2636 Register tmp = input_reg.is(rax) ? rcx : rax; |
| 2618 Register tmp2 = tmp.is(rcx) ? rdx : input_reg.is(rcx) ? rdx : rcx; | 2637 Register tmp2 = tmp.is(rcx) ? rdx : input_reg.is(rcx) ? rdx : rcx; |
| 2619 | 2638 |
| 2620 // Preserve the value of all registers. | 2639 // Preserve the value of all registers. |
| 2621 PushSafepointRegistersScope scope(this); | 2640 PushSafepointRegistersScope scope(this); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2632 | 2651 |
| 2633 __ bind(&negative); | 2652 __ bind(&negative); |
| 2634 | 2653 |
| 2635 Label allocated, slow; | 2654 Label allocated, slow; |
| 2636 __ AllocateHeapNumber(tmp, tmp2, &slow); | 2655 __ AllocateHeapNumber(tmp, tmp2, &slow); |
| 2637 __ jmp(&allocated); | 2656 __ jmp(&allocated); |
| 2638 | 2657 |
| 2639 // Slow case: Call the runtime system to do the number allocation. | 2658 // Slow case: Call the runtime system to do the number allocation. |
| 2640 __ bind(&slow); | 2659 __ bind(&slow); |
| 2641 | 2660 |
| 2642 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 2661 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr, |
| 2662 instr->context()); |
| 2643 // Set the pointer to the new heap number in tmp. | 2663 // Set the pointer to the new heap number in tmp. |
| 2644 if (!tmp.is(rax)) { | 2664 if (!tmp.is(rax)) { |
| 2645 __ movq(tmp, rax); | 2665 __ movq(tmp, rax); |
| 2646 } | 2666 } |
| 2647 | 2667 |
| 2648 // Restore input_reg after call to runtime. | 2668 // Restore input_reg after call to runtime. |
| 2649 __ LoadFromSafepointRegisterSlot(input_reg, input_reg); | 2669 __ LoadFromSafepointRegisterSlot(input_reg, input_reg); |
| 2650 | 2670 |
| 2651 __ bind(&allocated); | 2671 __ bind(&allocated); |
| 2652 __ movq(tmp2, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 2672 __ movq(tmp2, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 2653 __ shl(tmp2, Immediate(1)); | 2673 __ shl(tmp2, Immediate(1)); |
| 2654 __ shr(tmp2, Immediate(1)); | 2674 __ shr(tmp2, Immediate(1)); |
| 2655 __ movq(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2); | 2675 __ movq(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2); |
| 2656 __ StoreToSafepointRegisterSlot(input_reg, tmp); | 2676 __ StoreToSafepointRegisterSlot(input_reg, tmp); |
| 2657 | 2677 |
| 2658 __ bind(&done); | 2678 __ bind(&done); |
| 2659 } | 2679 } |
| 2660 | 2680 |
| 2661 | 2681 |
| 2662 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { | 2682 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { |
| 2663 Register input_reg = ToRegister(instr->InputAt(0)); | 2683 Register input_reg = ToRegister(instr->value()); |
| 2664 __ testl(input_reg, input_reg); | 2684 __ testl(input_reg, input_reg); |
| 2665 Label is_positive; | 2685 Label is_positive; |
| 2666 __ j(not_sign, &is_positive); | 2686 __ j(not_sign, &is_positive); |
| 2667 __ negl(input_reg); // Sets flags. | 2687 __ negl(input_reg); // Sets flags. |
| 2668 DeoptimizeIf(negative, instr->environment()); | 2688 DeoptimizeIf(negative, instr->environment()); |
| 2669 __ bind(&is_positive); | 2689 __ bind(&is_positive); |
| 2670 } | 2690 } |
| 2671 | 2691 |
| 2672 | 2692 |
| 2673 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { | 2693 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { |
| 2674 // Class for deferred case. | 2694 // Class for deferred case. |
| 2675 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { | 2695 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { |
| 2676 public: | 2696 public: |
| 2677 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, | 2697 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, |
| 2678 LUnaryMathOperation* instr) | 2698 LUnaryMathOperation* instr) |
| 2679 : LDeferredCode(codegen), instr_(instr) { } | 2699 : LDeferredCode(codegen), instr_(instr) { } |
| 2680 virtual void Generate() { | 2700 virtual void Generate() { |
| 2681 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); | 2701 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
| 2682 } | 2702 } |
| 2683 private: | 2703 private: |
| 2684 LUnaryMathOperation* instr_; | 2704 LUnaryMathOperation* instr_; |
| 2685 }; | 2705 }; |
| 2686 | 2706 |
| 2687 ASSERT(instr->InputAt(0)->Equals(instr->result())); | 2707 ASSERT(instr->value()->Equals(instr->result())); |
| 2688 Representation r = instr->hydrogen()->value()->representation(); | 2708 Representation r = instr->hydrogen()->value()->representation(); |
| 2689 | 2709 |
| 2690 if (r.IsDouble()) { | 2710 if (r.IsDouble()) { |
| 2691 XMMRegister scratch = xmm0; | 2711 XMMRegister scratch = xmm0; |
| 2692 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 2712 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 2693 __ xorps(scratch, scratch); | 2713 __ xorps(scratch, scratch); |
| 2694 __ subsd(scratch, input_reg); | 2714 __ subsd(scratch, input_reg); |
| 2695 __ andpd(input_reg, scratch); | 2715 __ andpd(input_reg, scratch); |
| 2696 } else if (r.IsInteger32()) { | 2716 } else if (r.IsInteger32()) { |
| 2697 EmitIntegerMathAbs(instr); | 2717 EmitIntegerMathAbs(instr); |
| 2698 } else { // Tagged case. | 2718 } else { // Tagged case. |
| 2699 DeferredMathAbsTaggedHeapNumber* deferred = | 2719 DeferredMathAbsTaggedHeapNumber* deferred = |
| 2700 new DeferredMathAbsTaggedHeapNumber(this, instr); | 2720 new DeferredMathAbsTaggedHeapNumber(this, instr); |
| 2701 Register input_reg = ToRegister(instr->InputAt(0)); | 2721 Register input_reg = ToRegister(instr->value()); |
| 2702 // Smi check. | 2722 // Smi check. |
| 2703 __ JumpIfNotSmi(input_reg, deferred->entry()); | 2723 __ JumpIfNotSmi(input_reg, deferred->entry()); |
| 2704 __ SmiToInteger32(input_reg, input_reg); | 2724 __ SmiToInteger32(input_reg, input_reg); |
| 2705 EmitIntegerMathAbs(instr); | 2725 EmitIntegerMathAbs(instr); |
| 2706 __ Integer32ToSmi(input_reg, input_reg); | 2726 __ Integer32ToSmi(input_reg, input_reg); |
| 2707 __ bind(deferred->exit()); | 2727 __ bind(deferred->exit()); |
| 2708 } | 2728 } |
| 2709 } | 2729 } |
| 2710 | 2730 |
| 2711 | 2731 |
| 2712 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { | 2732 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { |
| 2713 XMMRegister xmm_scratch = xmm0; | 2733 XMMRegister xmm_scratch = xmm0; |
| 2714 Register output_reg = ToRegister(instr->result()); | 2734 Register output_reg = ToRegister(instr->result()); |
| 2715 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 2735 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 2716 Label done; | 2736 Label done; |
| 2717 | 2737 |
| 2718 if (CpuFeatures::IsSupported(SSE4_1)) { | 2738 if (CpuFeatures::IsSupported(SSE4_1)) { |
| 2719 CpuFeatures::Scope scope(SSE4_1); | 2739 CpuFeatures::Scope scope(SSE4_1); |
| 2720 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 2740 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 2721 // Deoptimize if minus zero. | 2741 // Deoptimize if minus zero. |
| 2722 __ movq(output_reg, input_reg); | 2742 __ movq(output_reg, input_reg); |
| 2723 __ subq(output_reg, Immediate(1)); | 2743 __ subq(output_reg, Immediate(1)); |
| 2724 DeoptimizeIf(overflow, instr->environment()); | 2744 DeoptimizeIf(overflow, instr->environment()); |
| 2725 } | 2745 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2751 __ cmpl(output_reg, Immediate(0x80000000)); | 2771 __ cmpl(output_reg, Immediate(0x80000000)); |
| 2752 DeoptimizeIf(equal, instr->environment()); | 2772 DeoptimizeIf(equal, instr->environment()); |
| 2753 } | 2773 } |
| 2754 __ bind(&done); | 2774 __ bind(&done); |
| 2755 } | 2775 } |
| 2756 | 2776 |
| 2757 | 2777 |
| 2758 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { | 2778 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { |
| 2759 const XMMRegister xmm_scratch = xmm0; | 2779 const XMMRegister xmm_scratch = xmm0; |
| 2760 Register output_reg = ToRegister(instr->result()); | 2780 Register output_reg = ToRegister(instr->result()); |
| 2761 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 2781 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 2762 | 2782 |
| 2763 Label done; | 2783 Label done; |
| 2764 // xmm_scratch = 0.5 | 2784 // xmm_scratch = 0.5 |
| 2765 __ movq(kScratchRegister, V8_INT64_C(0x3FE0000000000000), RelocInfo::NONE); | 2785 __ movq(kScratchRegister, V8_INT64_C(0x3FE0000000000000), RelocInfo::NONE); |
| 2766 __ movq(xmm_scratch, kScratchRegister); | 2786 __ movq(xmm_scratch, kScratchRegister); |
| 2767 Label below_half; | 2787 Label below_half; |
| 2768 __ ucomisd(xmm_scratch, input_reg); | 2788 __ ucomisd(xmm_scratch, input_reg); |
| 2769 // If input_reg is NaN, this doesn't jump. | 2789 // If input_reg is NaN, this doesn't jump. |
| 2770 __ j(above, &below_half, Label::kNear); | 2790 __ j(above, &below_half, Label::kNear); |
| 2771 // input = input + 0.5 | 2791 // input = input + 0.5 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2796 __ ucomisd(input_reg, xmm_scratch); | 2816 __ ucomisd(input_reg, xmm_scratch); |
| 2797 DeoptimizeIf(below, instr->environment()); | 2817 DeoptimizeIf(below, instr->environment()); |
| 2798 } | 2818 } |
| 2799 __ xorl(output_reg, output_reg); | 2819 __ xorl(output_reg, output_reg); |
| 2800 | 2820 |
| 2801 __ bind(&done); | 2821 __ bind(&done); |
| 2802 } | 2822 } |
| 2803 | 2823 |
| 2804 | 2824 |
| 2805 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { | 2825 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { |
| 2806 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 2826 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 2807 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); | 2827 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
| 2808 __ sqrtsd(input_reg, input_reg); | 2828 __ sqrtsd(input_reg, input_reg); |
| 2809 } | 2829 } |
| 2810 | 2830 |
| 2811 | 2831 |
| 2812 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { | 2832 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { |
| 2813 XMMRegister xmm_scratch = xmm0; | 2833 XMMRegister xmm_scratch = xmm0; |
| 2814 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 2834 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 2815 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); | 2835 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
| 2816 __ xorps(xmm_scratch, xmm_scratch); | 2836 __ xorps(xmm_scratch, xmm_scratch); |
| 2817 __ addsd(input_reg, xmm_scratch); // Convert -0 to +0. | 2837 __ addsd(input_reg, xmm_scratch); // Convert -0 to +0. |
| 2818 __ sqrtsd(input_reg, input_reg); | 2838 __ sqrtsd(input_reg, input_reg); |
| 2819 } | 2839 } |
| 2820 | 2840 |
| 2821 | 2841 |
| 2822 void LCodeGen::DoPower(LPower* instr) { | 2842 void LCodeGen::DoPower(LPower* instr) { |
| 2823 LOperand* left = instr->InputAt(0); | 2843 LOperand* left = instr->InputAt(0); |
| 2824 XMMRegister left_reg = ToDoubleRegister(left); | 2844 XMMRegister left_reg = ToDoubleRegister(left); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2865 // Move arguments to correct registers xmm0 and xmm1. | 2885 // Move arguments to correct registers xmm0 and xmm1. |
| 2866 __ movaps(xmm0, left_reg); | 2886 __ movaps(xmm0, left_reg); |
| 2867 // Right argument is already in xmm1. | 2887 // Right argument is already in xmm1. |
| 2868 __ CallCFunction( | 2888 __ CallCFunction( |
| 2869 ExternalReference::power_double_double_function(isolate()), 2); | 2889 ExternalReference::power_double_double_function(isolate()), 2); |
| 2870 } | 2890 } |
| 2871 // Return value is in xmm0. | 2891 // Return value is in xmm0. |
| 2872 __ movaps(result_reg, xmm0); | 2892 __ movaps(result_reg, xmm0); |
| 2873 // Restore context register. | 2893 // Restore context register. |
| 2874 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2894 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 2895 __ movq(rsi, Immediate(0)); |
| 2875 } | 2896 } |
| 2876 | 2897 |
| 2877 | 2898 |
| 2878 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { | 2899 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { |
| 2879 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | 2900 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
| 2880 TranscendentalCacheStub stub(TranscendentalCache::LOG, | 2901 TranscendentalCacheStub stub(TranscendentalCache::LOG, |
| 2881 TranscendentalCacheStub::UNTAGGED); | 2902 TranscendentalCacheStub::UNTAGGED); |
| 2882 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 2903 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 2883 } | 2904 } |
| 2884 | 2905 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2937 ASSERT(instr->HasPointerMap()); | 2958 ASSERT(instr->HasPointerMap()); |
| 2938 ASSERT(instr->HasDeoptimizationEnvironment()); | 2959 ASSERT(instr->HasDeoptimizationEnvironment()); |
| 2939 LPointerMap* pointers = instr->pointer_map(); | 2960 LPointerMap* pointers = instr->pointer_map(); |
| 2940 LEnvironment* env = instr->deoptimization_environment(); | 2961 LEnvironment* env = instr->deoptimization_environment(); |
| 2941 RecordPosition(pointers->position()); | 2962 RecordPosition(pointers->position()); |
| 2942 RegisterEnvironmentForDeoptimization(env); | 2963 RegisterEnvironmentForDeoptimization(env); |
| 2943 SafepointGenerator generator(this, pointers, env->deoptimization_index()); | 2964 SafepointGenerator generator(this, pointers, env->deoptimization_index()); |
| 2944 ParameterCount count(instr->arity()); | 2965 ParameterCount count(instr->arity()); |
| 2945 __ InvokeFunction(rdi, count, CALL_FUNCTION, generator, CALL_AS_METHOD); | 2966 __ InvokeFunction(rdi, count, CALL_FUNCTION, generator, CALL_AS_METHOD); |
| 2946 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2967 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 2968 __ movq(rsi, Immediate(0)); |
| 2947 } | 2969 } |
| 2948 | 2970 |
| 2949 | 2971 |
| 2950 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { | 2972 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { |
| 2951 ASSERT(ToRegister(instr->key()).is(rcx)); | 2973 ASSERT(ToRegister(instr->key()).is(rcx)); |
| 2952 ASSERT(ToRegister(instr->result()).is(rax)); | 2974 ASSERT(ToRegister(instr->result()).is(rax)); |
| 2953 | 2975 |
| 2954 int arity = instr->arity(); | 2976 int arity = instr->arity(); |
| 2955 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize( | 2977 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize( |
| 2956 arity, NOT_IN_LOOP); | 2978 arity, NOT_IN_LOOP); |
| 2957 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2979 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2958 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2980 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 2981 __ movq(rsi, Immediate(0)); |
| 2959 } | 2982 } |
| 2960 | 2983 |
| 2961 | 2984 |
| 2962 void LCodeGen::DoCallNamed(LCallNamed* instr) { | 2985 void LCodeGen::DoCallNamed(LCallNamed* instr) { |
| 2963 ASSERT(ToRegister(instr->result()).is(rax)); | 2986 ASSERT(ToRegister(instr->result()).is(rax)); |
| 2964 | 2987 |
| 2965 int arity = instr->arity(); | 2988 int arity = instr->arity(); |
| 2966 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; | 2989 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; |
| 2967 Handle<Code> ic = | 2990 Handle<Code> ic = |
| 2968 isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_IN_LOOP, mode); | 2991 isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_IN_LOOP, mode); |
| 2969 __ Move(rcx, instr->name()); | 2992 __ Move(rcx, instr->name()); |
| 2970 CallCode(ic, mode, instr); | 2993 CallCode(ic, mode, instr); |
| 2971 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2994 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 2995 __ movq(rsi, Immediate(0)); |
| 2972 } | 2996 } |
| 2973 | 2997 |
| 2974 | 2998 |
| 2975 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 2999 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
| 2976 ASSERT(ToRegister(instr->result()).is(rax)); | 3000 ASSERT(ToRegister(instr->result()).is(rax)); |
| 2977 | 3001 |
| 2978 int arity = instr->arity(); | 3002 int arity = instr->arity(); |
| 2979 CallFunctionStub stub(arity, NOT_IN_LOOP, RECEIVER_MIGHT_BE_IMPLICIT); | 3003 CallFunctionStub stub(arity, NOT_IN_LOOP, RECEIVER_MIGHT_BE_IMPLICIT); |
| 2980 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 3004 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 2981 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 3005 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 3006 __ movq(rsi, Immediate(0)); |
| 2982 __ Drop(1); | 3007 __ Drop(1); |
| 2983 } | 3008 } |
| 2984 | 3009 |
| 2985 | 3010 |
| 2986 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { | 3011 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { |
| 2987 ASSERT(ToRegister(instr->result()).is(rax)); | 3012 ASSERT(ToRegister(instr->result()).is(rax)); |
| 2988 int arity = instr->arity(); | 3013 int arity = instr->arity(); |
| 2989 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; | 3014 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; |
| 2990 Handle<Code> ic = | 3015 Handle<Code> ic = |
| 2991 isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_IN_LOOP, mode); | 3016 isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_IN_LOOP, mode); |
| 2992 __ Move(rcx, instr->name()); | 3017 __ Move(rcx, instr->name()); |
| 2993 CallCode(ic, mode, instr); | 3018 CallCode(ic, mode, instr); |
| 3019 __ movq(rsi, Immediate(0)); |
| 2994 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 3020 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 3021 __ movq(rsi, Immediate(0)); |
| 2995 } | 3022 } |
| 2996 | 3023 |
| 2997 | 3024 |
| 2998 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { | 3025 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { |
| 2999 ASSERT(ToRegister(instr->result()).is(rax)); | 3026 ASSERT(ToRegister(instr->result()).is(rax)); |
| 3000 __ Move(rdi, instr->target()); | 3027 __ Move(rdi, instr->target()); |
| 3001 CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION); | 3028 CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION); |
| 3002 } | 3029 } |
| 3003 | 3030 |
| 3004 | 3031 |
| 3005 void LCodeGen::DoCallNew(LCallNew* instr) { | 3032 void LCodeGen::DoCallNew(LCallNew* instr) { |
| 3006 ASSERT(ToRegister(instr->InputAt(0)).is(rdi)); | 3033 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 3034 ASSERT(ToRegister(instr->constructor()).is(rdi)); |
| 3007 ASSERT(ToRegister(instr->result()).is(rax)); | 3035 ASSERT(ToRegister(instr->result()).is(rax)); |
| 3008 | 3036 |
| 3009 Handle<Code> builtin = isolate()->builtins()->JSConstructCall(); | 3037 Handle<Code> builtin = isolate()->builtins()->JSConstructCall(); |
| 3010 __ Set(rax, instr->arity()); | 3038 __ Set(rax, instr->arity()); |
| 3011 CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr); | 3039 CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr); |
| 3012 } | 3040 } |
| 3013 | 3041 |
| 3014 | 3042 |
| 3015 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 3043 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
| 3016 CallRuntime(instr->function(), instr->arity(), instr); | 3044 CallRuntime(instr->function(), instr->arity(), instr); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 3041 if (instr->needs_write_barrier()) { | 3069 if (instr->needs_write_barrier()) { |
| 3042 // Update the write barrier for the properties array. | 3070 // Update the write barrier for the properties array. |
| 3043 // object is used as a scratch register. | 3071 // object is used as a scratch register. |
| 3044 __ RecordWrite(temp, offset, value, object); | 3072 __ RecordWrite(temp, offset, value, object); |
| 3045 } | 3073 } |
| 3046 } | 3074 } |
| 3047 } | 3075 } |
| 3048 | 3076 |
| 3049 | 3077 |
| 3050 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { | 3078 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { |
| 3079 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 3051 ASSERT(ToRegister(instr->object()).is(rdx)); | 3080 ASSERT(ToRegister(instr->object()).is(rdx)); |
| 3052 ASSERT(ToRegister(instr->value()).is(rax)); | 3081 ASSERT(ToRegister(instr->value()).is(rax)); |
| 3053 | 3082 |
| 3054 __ Move(rcx, instr->hydrogen()->name()); | 3083 __ Move(rcx, instr->hydrogen()->name()); |
| 3055 Handle<Code> ic = instr->strict_mode() | 3084 Handle<Code> ic = instr->strict_mode() |
| 3056 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 3085 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 3057 : isolate()->builtins()->StoreIC_Initialize(); | 3086 : isolate()->builtins()->StoreIC_Initialize(); |
| 3058 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3087 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 3059 } | 3088 } |
| 3060 | 3089 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3163 __ movq(value, kScratchRegister); | 3192 __ movq(value, kScratchRegister); |
| 3164 | 3193 |
| 3165 __ bind(&have_value); | 3194 __ bind(&have_value); |
| 3166 Operand double_store_operand = BuildFastArrayOperand( | 3195 Operand double_store_operand = BuildFastArrayOperand( |
| 3167 instr->elements(), instr->key(), JSObject::FAST_DOUBLE_ELEMENTS, | 3196 instr->elements(), instr->key(), JSObject::FAST_DOUBLE_ELEMENTS, |
| 3168 FixedDoubleArray::kHeaderSize - kHeapObjectTag); | 3197 FixedDoubleArray::kHeaderSize - kHeapObjectTag); |
| 3169 __ movsd(double_store_operand, value); | 3198 __ movsd(double_store_operand, value); |
| 3170 } | 3199 } |
| 3171 | 3200 |
| 3172 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { | 3201 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
| 3202 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 3173 ASSERT(ToRegister(instr->object()).is(rdx)); | 3203 ASSERT(ToRegister(instr->object()).is(rdx)); |
| 3174 ASSERT(ToRegister(instr->key()).is(rcx)); | 3204 ASSERT(ToRegister(instr->key()).is(rcx)); |
| 3175 ASSERT(ToRegister(instr->value()).is(rax)); | 3205 ASSERT(ToRegister(instr->value()).is(rax)); |
| 3176 | 3206 |
| 3177 Handle<Code> ic = instr->strict_mode() | 3207 Handle<Code> ic = instr->strict_mode() |
| 3178 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 3208 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
| 3179 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 3209 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
| 3180 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3210 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 3181 } | 3211 } |
| 3182 | 3212 |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3293 // DoStringCharCodeAt above. | 3323 // DoStringCharCodeAt above. |
| 3294 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); | 3324 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); |
| 3295 if (instr->index()->IsConstantOperand()) { | 3325 if (instr->index()->IsConstantOperand()) { |
| 3296 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); | 3326 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
| 3297 __ Push(Smi::FromInt(const_index)); | 3327 __ Push(Smi::FromInt(const_index)); |
| 3298 } else { | 3328 } else { |
| 3299 Register index = ToRegister(instr->index()); | 3329 Register index = ToRegister(instr->index()); |
| 3300 __ Integer32ToSmi(index, index); | 3330 __ Integer32ToSmi(index, index); |
| 3301 __ push(index); | 3331 __ push(index); |
| 3302 } | 3332 } |
| 3303 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr); | 3333 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, |
| 3334 instr, instr->context()); |
| 3304 if (FLAG_debug_code) { | 3335 if (FLAG_debug_code) { |
| 3305 __ AbortIfNotSmi(rax); | 3336 __ AbortIfNotSmi(rax); |
| 3306 } | 3337 } |
| 3307 __ SmiToInteger32(rax, rax); | 3338 __ SmiToInteger32(rax, rax); |
| 3308 __ StoreToSafepointRegisterSlot(result, rax); | 3339 __ StoreToSafepointRegisterSlot(result, rax); |
| 3309 } | 3340 } |
| 3310 | 3341 |
| 3311 | 3342 |
| 3312 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { | 3343 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { |
| 3313 class DeferredStringCharFromCode: public LDeferredCode { | 3344 class DeferredStringCharFromCode: public LDeferredCode { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 3344 Register result = ToRegister(instr->result()); | 3375 Register result = ToRegister(instr->result()); |
| 3345 | 3376 |
| 3346 // TODO(3095996): Get rid of this. For now, we need to make the | 3377 // TODO(3095996): Get rid of this. For now, we need to make the |
| 3347 // result register contain a valid pointer because it is already | 3378 // result register contain a valid pointer because it is already |
| 3348 // contained in the register pointer map. | 3379 // contained in the register pointer map. |
| 3349 __ Set(result, 0); | 3380 __ Set(result, 0); |
| 3350 | 3381 |
| 3351 PushSafepointRegistersScope scope(this); | 3382 PushSafepointRegistersScope scope(this); |
| 3352 __ Integer32ToSmi(char_code, char_code); | 3383 __ Integer32ToSmi(char_code, char_code); |
| 3353 __ push(char_code); | 3384 __ push(char_code); |
| 3354 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr); | 3385 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context()); |
| 3355 __ StoreToSafepointRegisterSlot(result, rax); | 3386 __ StoreToSafepointRegisterSlot(result, rax); |
| 3356 } | 3387 } |
| 3357 | 3388 |
| 3358 | 3389 |
| 3359 void LCodeGen::DoStringLength(LStringLength* instr) { | 3390 void LCodeGen::DoStringLength(LStringLength* instr) { |
| 3360 Register string = ToRegister(instr->string()); | 3391 Register string = ToRegister(instr->string()); |
| 3361 Register result = ToRegister(instr->result()); | 3392 Register result = ToRegister(instr->result()); |
| 3362 __ movq(result, FieldOperand(string, String::kLengthOffset)); | 3393 __ movq(result, FieldOperand(string, String::kLengthOffset)); |
| 3363 } | 3394 } |
| 3364 | 3395 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3412 | 3443 |
| 3413 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 3444 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
| 3414 // TODO(3095996): Get rid of this. For now, we need to make the | 3445 // TODO(3095996): Get rid of this. For now, we need to make the |
| 3415 // result register contain a valid pointer because it is already | 3446 // result register contain a valid pointer because it is already |
| 3416 // contained in the register pointer map. | 3447 // contained in the register pointer map. |
| 3417 Register reg = ToRegister(instr->result()); | 3448 Register reg = ToRegister(instr->result()); |
| 3418 __ Move(reg, Smi::FromInt(0)); | 3449 __ Move(reg, Smi::FromInt(0)); |
| 3419 | 3450 |
| 3420 { | 3451 { |
| 3421 PushSafepointRegistersScope scope(this); | 3452 PushSafepointRegistersScope scope(this); |
| 3422 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 3453 // NumberTagD uses the context from the frame, rather than |
| 3454 // the environment's HContext or HInlinedContext value. |
| 3455 // It only calls Runtime::kAllocateHeapNumber. |
| 3456 // The corresponding HChange instructions are added in a phase that does |
| 3457 // not have easy access to the local context. |
| 3458 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 3459 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
| 3460 RecordSafepointWithRegisters(instr->pointer_map(), 0, |
| 3461 Safepoint::kNoDeoptimizationIndex); |
| 3423 // Ensure that value in rax survives popping registers. | 3462 // Ensure that value in rax survives popping registers. |
| 3424 __ movq(kScratchRegister, rax); | 3463 __ movq(kScratchRegister, rax); |
| 3425 } | 3464 } |
| 3426 __ movq(reg, kScratchRegister); | 3465 __ movq(reg, kScratchRegister); |
| 3427 } | 3466 } |
| 3428 | 3467 |
| 3429 | 3468 |
| 3430 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 3469 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
| 3431 ASSERT(instr->InputAt(0)->Equals(instr->result())); | 3470 ASSERT(instr->InputAt(0)->Equals(instr->result())); |
| 3432 Register input = ToRegister(instr->InputAt(0)); | 3471 Register input = ToRegister(instr->InputAt(0)); |
| (...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3877 __ movq(FieldOperand(rax, i + kPointerSize), rcx); | 3916 __ movq(FieldOperand(rax, i + kPointerSize), rcx); |
| 3878 } | 3917 } |
| 3879 if ((size % (2 * kPointerSize)) != 0) { | 3918 if ((size % (2 * kPointerSize)) != 0) { |
| 3880 __ movq(rdx, FieldOperand(rbx, size - kPointerSize)); | 3919 __ movq(rdx, FieldOperand(rbx, size - kPointerSize)); |
| 3881 __ movq(FieldOperand(rax, size - kPointerSize), rdx); | 3920 __ movq(FieldOperand(rax, size - kPointerSize), rdx); |
| 3882 } | 3921 } |
| 3883 } | 3922 } |
| 3884 | 3923 |
| 3885 | 3924 |
| 3886 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { | 3925 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { |
| 3926 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 3887 // Use the fast case closure allocation code that allocates in new | 3927 // Use the fast case closure allocation code that allocates in new |
| 3888 // space for nested functions that don't need literals cloning. | 3928 // space for nested functions that don't need literals cloning. |
| 3889 Handle<SharedFunctionInfo> shared_info = instr->shared_info(); | 3929 Handle<SharedFunctionInfo> shared_info = instr->shared_info(); |
| 3890 bool pretenure = instr->hydrogen()->pretenure(); | 3930 bool pretenure = instr->hydrogen()->pretenure(); |
| 3891 if (!pretenure && shared_info->num_literals() == 0) { | 3931 if (!pretenure && shared_info->num_literals() == 0) { |
| 3892 FastNewClosureStub stub( | 3932 FastNewClosureStub stub( |
| 3893 shared_info->strict_mode() ? kStrictMode : kNonStrictMode); | 3933 shared_info->strict_mode() ? kStrictMode : kNonStrictMode); |
| 3894 __ Push(shared_info); | 3934 __ Push(shared_info); |
| 3895 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 3935 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 3896 } else { | 3936 } else { |
| 3897 __ push(rsi); | 3937 __ push(rsi); |
| 3898 __ Push(shared_info); | 3938 __ Push(shared_info); |
| 3899 __ PushRoot(pretenure ? | 3939 __ PushRoot(pretenure ? |
| 3900 Heap::kTrueValueRootIndex : | 3940 Heap::kTrueValueRootIndex : |
| 3901 Heap::kFalseValueRootIndex); | 3941 Heap::kFalseValueRootIndex); |
| 3902 CallRuntime(Runtime::kNewClosure, 3, instr); | 3942 CallRuntime(Runtime::kNewClosure, 3, instr); |
| 3903 } | 3943 } |
| 3904 } | 3944 } |
| 3905 | 3945 |
| 3906 | 3946 |
| 3907 void LCodeGen::DoTypeof(LTypeof* instr) { | 3947 void LCodeGen::DoTypeof(LTypeof* instr) { |
| 3908 LOperand* input = instr->InputAt(0); | 3948 LOperand* input = instr->value(); |
| 3909 EmitPushTaggedOperand(input); | 3949 EmitPushTaggedOperand(input); |
| 3910 CallRuntime(Runtime::kTypeof, 1, instr); | 3950 CallRuntime(Runtime::kTypeof, 1, instr); |
| 3911 } | 3951 } |
| 3912 | 3952 |
| 3913 | 3953 |
| 3914 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { | 3954 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { |
| 3915 ASSERT(!operand->IsDoubleRegister()); | 3955 ASSERT(!operand->IsDoubleRegister()); |
| 3916 if (operand->IsConstantOperand()) { | 3956 if (operand->IsConstantOperand()) { |
| 3917 __ Push(ToHandle(LConstantOperand::cast(operand))); | 3957 __ Push(ToHandle(LConstantOperand::cast(operand))); |
| 3918 } else if (operand->IsRegister()) { | 3958 } else if (operand->IsRegister()) { |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4083 // builtin) | 4123 // builtin) |
| 4084 SafepointGenerator safepoint_generator(this, | 4124 SafepointGenerator safepoint_generator(this, |
| 4085 pointers, | 4125 pointers, |
| 4086 env->deoptimization_index()); | 4126 env->deoptimization_index()); |
| 4087 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); | 4127 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); |
| 4088 } | 4128 } |
| 4089 | 4129 |
| 4090 | 4130 |
| 4091 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { | 4131 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { |
| 4092 { | 4132 { |
| 4133 |
| 4093 PushSafepointRegistersScope scope(this); | 4134 PushSafepointRegistersScope scope(this); |
| 4094 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 4135 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 4095 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); | 4136 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); |
| 4096 RegisterLazyDeoptimization(instr, RECORD_SAFEPOINT_WITH_REGISTERS, 0); | 4137 RegisterLazyDeoptimization(instr, RECORD_SAFEPOINT_WITH_REGISTERS, 0); |
| 4097 } | 4138 } |
| 4098 | 4139 |
| 4099 // The gap code includes the restoring of the safepoint registers. | 4140 // The gap code includes the restoring of the safepoint registers. |
| 4100 int pc = masm()->pc_offset(); | 4141 int pc = masm()->pc_offset(); |
| 4101 safepoints_.SetPcAfterGap(pc); | 4142 safepoints_.SetPcAfterGap(pc); |
| 4102 } | 4143 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4147 RegisterEnvironmentForDeoptimization(environment); | 4188 RegisterEnvironmentForDeoptimization(environment); |
| 4148 ASSERT(osr_pc_offset_ == -1); | 4189 ASSERT(osr_pc_offset_ == -1); |
| 4149 osr_pc_offset_ = masm()->pc_offset(); | 4190 osr_pc_offset_ = masm()->pc_offset(); |
| 4150 } | 4191 } |
| 4151 | 4192 |
| 4152 #undef __ | 4193 #undef __ |
| 4153 | 4194 |
| 4154 } } // namespace v8::internal | 4195 } } // namespace v8::internal |
| 4155 | 4196 |
| 4156 #endif // V8_TARGET_ARCH_X64 | 4197 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |