| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 RelocInfo::Mode mode, | 405 RelocInfo::Mode mode, |
| 406 LInstruction* instr) { | 406 LInstruction* instr) { |
| 407 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT); | 407 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT); |
| 408 } | 408 } |
| 409 | 409 |
| 410 | 410 |
| 411 void LCodeGen::CallCodeGeneric(Handle<Code> code, | 411 void LCodeGen::CallCodeGeneric(Handle<Code> code, |
| 412 RelocInfo::Mode mode, | 412 RelocInfo::Mode mode, |
| 413 LInstruction* instr, | 413 LInstruction* instr, |
| 414 SafepointMode safepoint_mode) { | 414 SafepointMode safepoint_mode) { |
| 415 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | |
| 416 ASSERT(instr != NULL); | 415 ASSERT(instr != NULL); |
| 417 | 416 |
| 418 Assembler::BlockConstPoolScope scope(masm_); | 417 Assembler::BlockConstPoolScope scope(masm_); |
| 419 __ Call(code, mode); | 418 __ Call(code, mode); |
| 420 RecordSafepointWithLazyDeopt(instr, safepoint_mode); | 419 RecordSafepointWithLazyDeopt(instr, safepoint_mode); |
| 421 | 420 |
| 422 if ((code->kind() == Code::BINARY_OP_IC) || | 421 if ((code->kind() == Code::BINARY_OP_IC) || |
| 423 (code->kind() == Code::COMPARE_IC)) { | 422 (code->kind() == Code::COMPARE_IC)) { |
| 424 // Signal that we don't inline smi code before these stubs in the | 423 // Signal that we don't inline smi code before these stubs in the |
| 425 // optimizing code generator. | 424 // optimizing code generator. |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 659 | 658 |
| 660 // TODO(all): Add support for stop_t FLAG in DEBUG mode. | 659 // TODO(all): Add support for stop_t FLAG in DEBUG mode. |
| 661 | 660 |
| 662 // Classic mode functions and builtins need to replace the receiver with the | 661 // Classic mode functions and builtins need to replace the receiver with the |
| 663 // global proxy when called as functions (without an explicit receiver | 662 // global proxy when called as functions (without an explicit receiver |
| 664 // object). | 663 // object). |
| 665 if (info_->this_has_uses() && | 664 if (info_->this_has_uses() && |
| 666 info_->is_classic_mode() && | 665 info_->is_classic_mode() && |
| 667 !info_->is_native()) { | 666 !info_->is_native()) { |
| 668 Label ok; | 667 Label ok; |
| 669 __ Cbz(x5, &ok); | |
| 670 int receiver_offset = info_->scope()->num_parameters() * kXRegSizeInBytes; | 668 int receiver_offset = info_->scope()->num_parameters() * kXRegSizeInBytes; |
| 671 __ Peek(x10, receiver_offset); | 669 __ Peek(x10, receiver_offset); |
| 672 __ JumpIfNotRoot(x10, Heap::kUndefinedValueRootIndex, &ok); | 670 __ JumpIfNotRoot(x10, Heap::kUndefinedValueRootIndex, &ok); |
| 673 | 671 |
| 674 __ Ldr(x10, GlobalObjectMemOperand()); | 672 __ Ldr(x10, GlobalObjectMemOperand()); |
| 675 __ Ldr(x10, FieldMemOperand(x10, GlobalObject::kGlobalReceiverOffset)); | 673 __ Ldr(x10, FieldMemOperand(x10, GlobalObject::kGlobalReceiverOffset)); |
| 676 __ Poke(x10, receiver_offset); | 674 __ Poke(x10, receiver_offset); |
| 677 | 675 |
| 678 __ Bind(&ok); | 676 __ Bind(&ok); |
| 679 } | 677 } |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1056 Heap::RootListIndex index, | 1054 Heap::RootListIndex index, |
| 1057 LEnvironment* environment) { | 1055 LEnvironment* environment) { |
| 1058 Label dont_deopt; | 1056 Label dont_deopt; |
| 1059 __ JumpIfRoot(rt, index, &dont_deopt); | 1057 __ JumpIfRoot(rt, index, &dont_deopt); |
| 1060 Deoptimize(environment); | 1058 Deoptimize(environment); |
| 1061 __ Bind(&dont_deopt); | 1059 __ Bind(&dont_deopt); |
| 1062 } | 1060 } |
| 1063 | 1061 |
| 1064 | 1062 |
| 1065 void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) { | 1063 void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) { |
| 1066 if (info()->IsStub()) return; | 1064 if (!info()->IsStub()) { |
| 1067 // Ensure that we have enough space after the previous lazy-bailout | 1065 // Ensure that we have enough space after the previous lazy-bailout |
| 1068 // instruction for patching the code here. | 1066 // instruction for patching the code here. |
| 1069 intptr_t current_pc = masm()->pc_offset(); | 1067 intptr_t current_pc = masm()->pc_offset(); |
| 1070 | 1068 |
| 1071 if (current_pc < (last_lazy_deopt_pc_ + space_needed)) { | 1069 if (current_pc < (last_lazy_deopt_pc_ + space_needed)) { |
| 1072 ptrdiff_t padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; | 1070 ptrdiff_t padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; |
| 1073 ASSERT((padding_size % kInstructionSize) == 0); | 1071 ASSERT((padding_size % kInstructionSize) == 0); |
| 1074 InstructionAccurateScope instruction_accurate( | 1072 InstructionAccurateScope instruction_accurate( |
| 1075 masm(), padding_size / kInstructionSize); | 1073 masm(), padding_size / kInstructionSize); |
| 1076 | 1074 |
| 1077 while (padding_size > 0) { | 1075 while (padding_size > 0) { |
| 1078 __ nop(); | 1076 __ nop(); |
| 1079 padding_size -= kInstructionSize; | 1077 padding_size -= kInstructionSize; |
| 1078 } |
| 1080 } | 1079 } |
| 1081 } | 1080 } |
| 1081 last_lazy_deopt_pc_ = masm()->pc_offset(); |
| 1082 } | 1082 } |
| 1083 | 1083 |
| 1084 | 1084 |
| 1085 Register LCodeGen::ToRegister(LOperand* op) const { | 1085 Register LCodeGen::ToRegister(LOperand* op) const { |
| 1086 // TODO(all): support zero register results, as ToRegister32. | 1086 // TODO(all): support zero register results, as ToRegister32. |
| 1087 ASSERT((op != NULL) && op->IsRegister()); | 1087 ASSERT((op != NULL) && op->IsRegister()); |
| 1088 return Register::FromAllocationIndex(op->index()); | 1088 return Register::FromAllocationIndex(op->index()); |
| 1089 } | 1089 } |
| 1090 | 1090 |
| 1091 | 1091 |
| (...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1540 __ Subs(length, length, 1); | 1540 __ Subs(length, length, 1); |
| 1541 __ B(ne, &loop); | 1541 __ B(ne, &loop); |
| 1542 | 1542 |
| 1543 __ Bind(&invoke); | 1543 __ Bind(&invoke); |
| 1544 ASSERT(instr->HasPointerMap()); | 1544 ASSERT(instr->HasPointerMap()); |
| 1545 LPointerMap* pointers = instr->pointer_map(); | 1545 LPointerMap* pointers = instr->pointer_map(); |
| 1546 SafepointGenerator safepoint_generator(this, pointers, Safepoint::kLazyDeopt); | 1546 SafepointGenerator safepoint_generator(this, pointers, Safepoint::kLazyDeopt); |
| 1547 // The number of arguments is stored in argc (receiver) which is x0, as | 1547 // The number of arguments is stored in argc (receiver) which is x0, as |
| 1548 // expected by InvokeFunction. | 1548 // expected by InvokeFunction. |
| 1549 ParameterCount actual(argc); | 1549 ParameterCount actual(argc); |
| 1550 __ InvokeFunction(function, actual, CALL_FUNCTION, | 1550 __ InvokeFunction(function, actual, CALL_FUNCTION, safepoint_generator); |
| 1551 safepoint_generator, CALL_AS_FUNCTION); | |
| 1552 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1551 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 1553 } | 1552 } |
| 1554 | 1553 |
| 1555 | 1554 |
| 1556 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { | 1555 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
| 1557 Register result = ToRegister(instr->result()); | 1556 Register result = ToRegister(instr->result()); |
| 1558 | 1557 |
| 1559 if (instr->hydrogen()->from_inlined()) { | 1558 if (instr->hydrogen()->from_inlined()) { |
| 1560 // When we are inside an inlined function, the arguments are the last things | 1559 // When we are inside an inlined function, the arguments are the last things |
| 1561 // that have been pushed on the stack. Therefore the arguments array can be | 1560 // that have been pushed on the stack. Therefore the arguments array can be |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1849 } | 1848 } |
| 1850 } | 1849 } |
| 1851 } | 1850 } |
| 1852 } | 1851 } |
| 1853 | 1852 |
| 1854 | 1853 |
| 1855 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, | 1854 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, |
| 1856 int formal_parameter_count, | 1855 int formal_parameter_count, |
| 1857 int arity, | 1856 int arity, |
| 1858 LInstruction* instr, | 1857 LInstruction* instr, |
| 1859 CallKind call_kind, | |
| 1860 Register function_reg) { | 1858 Register function_reg) { |
| 1861 bool dont_adapt_arguments = | 1859 bool dont_adapt_arguments = |
| 1862 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; | 1860 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; |
| 1863 bool can_invoke_directly = | 1861 bool can_invoke_directly = |
| 1864 dont_adapt_arguments || formal_parameter_count == arity; | 1862 dont_adapt_arguments || formal_parameter_count == arity; |
| 1865 | 1863 |
| 1866 // The function interface relies on the following register assignments. | 1864 // The function interface relies on the following register assignments. |
| 1867 ASSERT(function_reg.Is(x1) || function_reg.IsNone()); | 1865 ASSERT(function_reg.Is(x1) || function_reg.IsNone()); |
| 1868 Register arity_reg = x0; | 1866 Register arity_reg = x0; |
| 1869 Register call_kind_reg = x5; | |
| 1870 | 1867 |
| 1871 LPointerMap* pointers = instr->pointer_map(); | 1868 LPointerMap* pointers = instr->pointer_map(); |
| 1872 | 1869 |
| 1873 // If necessary, load the function object. | 1870 // If necessary, load the function object. |
| 1874 if (function_reg.IsNone()) { | 1871 if (function_reg.IsNone()) { |
| 1875 function_reg = x1; | 1872 function_reg = x1; |
| 1876 __ LoadObject(function_reg, function); | 1873 __ LoadObject(function_reg, function); |
| 1877 } | 1874 } |
| 1878 | 1875 |
| 1879 if (FLAG_debug_code) { | 1876 if (FLAG_debug_code) { |
| 1880 Label is_not_smi; | 1877 Label is_not_smi; |
| 1881 // Try to confirm that function_reg (x1) is a tagged pointer. | 1878 // Try to confirm that function_reg (x1) is a tagged pointer. |
| 1882 __ JumpIfNotSmi(function_reg, &is_not_smi); | 1879 __ JumpIfNotSmi(function_reg, &is_not_smi); |
| 1883 __ Abort(kExpectedFunctionObject); | 1880 __ Abort(kExpectedFunctionObject); |
| 1884 __ Bind(&is_not_smi); | 1881 __ Bind(&is_not_smi); |
| 1885 } | 1882 } |
| 1886 | 1883 |
| 1887 if (can_invoke_directly) { | 1884 if (can_invoke_directly) { |
| 1888 // Change context. | 1885 // Change context. |
| 1889 __ Ldr(cp, FieldMemOperand(function_reg, JSFunction::kContextOffset)); | 1886 __ Ldr(cp, FieldMemOperand(function_reg, JSFunction::kContextOffset)); |
| 1890 | 1887 |
| 1891 // Set the arguments count if adaption is not needed. Assumes that x0 is | 1888 // Set the arguments count if adaption is not needed. Assumes that x0 is |
| 1892 // available to write to at this point. | 1889 // available to write to at this point. |
| 1893 if (dont_adapt_arguments) { | 1890 if (dont_adapt_arguments) { |
| 1894 __ Mov(arity_reg, arity); | 1891 __ Mov(arity_reg, arity); |
| 1895 } | 1892 } |
| 1896 | 1893 |
| 1897 // Invoke function. | 1894 // Invoke function. |
| 1898 __ SetCallKind(call_kind_reg, call_kind); | |
| 1899 __ Ldr(x10, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset)); | 1895 __ Ldr(x10, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset)); |
| 1900 __ Call(x10); | 1896 __ Call(x10); |
| 1901 | 1897 |
| 1902 // Set up deoptimization. | 1898 // Set up deoptimization. |
| 1903 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 1899 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
| 1904 } else { | 1900 } else { |
| 1905 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 1901 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 1906 ParameterCount count(arity); | 1902 ParameterCount count(arity); |
| 1907 ParameterCount expected(formal_parameter_count); | 1903 ParameterCount expected(formal_parameter_count); |
| 1908 __ InvokeFunction( | 1904 __ InvokeFunction(function_reg, expected, count, CALL_FUNCTION, generator); |
| 1909 function_reg, expected, count, CALL_FUNCTION, generator, call_kind); | |
| 1910 } | 1905 } |
| 1911 | 1906 |
| 1912 // Restore context. | 1907 // Restore context. |
| 1913 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1908 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 1914 } | 1909 } |
| 1915 | 1910 |
| 1916 | 1911 |
| 1917 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 1912 void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { |
| 1918 ASSERT(ToRegister(instr->result()).is(x0)); | 1913 ASSERT(instr->IsMarkedAsCall()); |
| 1919 CallKnownFunction(instr->hydrogen()->function(), | 1914 ASSERT(ToRegister(instr->result()).Is(x0)); |
| 1920 instr->hydrogen()->formal_parameter_count(), | 1915 |
| 1921 instr->arity(), instr, CALL_AS_FUNCTION); | 1916 LPointerMap* pointers = instr->pointer_map(); |
| 1917 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 1918 |
| 1919 if (instr->target()->IsConstantOperand()) { |
| 1920 LConstantOperand* target = LConstantOperand::cast(instr->target()); |
| 1921 Handle<Code> code = Handle<Code>::cast(ToHandle(target)); |
| 1922 generator.BeforeCall(__ CallSize(code, RelocInfo::CODE_TARGET)); |
| 1923 __ Call(code, RelocInfo::CODE_TARGET, TypeFeedbackId::None()); |
| 1924 } else { |
| 1925 ASSERT(instr->target()->IsRegister()); |
| 1926 Register target = ToRegister(instr->target()); |
| 1927 generator.BeforeCall(__ CallSize(target)); |
| 1928 __ Add(target, target, Code::kHeaderSize - kHeapObjectTag); |
| 1929 __ Call(target); |
| 1930 } |
| 1931 // TODO(jbramley): Is this load necessary? |
| 1932 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 1933 generator.AfterCall(); |
| 1922 } | 1934 } |
| 1923 | 1935 |
| 1924 | 1936 |
| 1925 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { | 1937 void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) { |
| 1926 ASSERT(ToRegister(instr->result()).is(x0)); | 1938 ASSERT(instr->IsMarkedAsCall()); |
| 1927 CallKnownFunction(instr->hydrogen()->target(), | 1939 ASSERT(ToRegister(instr->function()).is(x1)); |
| 1928 instr->hydrogen()->formal_parameter_count(), | 1940 |
| 1929 instr->arity(), instr, CALL_AS_FUNCTION); | 1941 if (instr->hydrogen()->pass_argument_count()) { |
| 1942 __ Mov(x0, Operand(instr->arity())); |
| 1943 } |
| 1944 |
| 1945 // Change context. |
| 1946 __ Ldr(cp, FieldMemOperand(x1, JSFunction::kContextOffset)); |
| 1947 |
| 1948 // Load the code entry address |
| 1949 __ Ldr(x10, FieldMemOperand(x1, JSFunction::kCodeEntryOffset)); |
| 1950 __ Call(x10); |
| 1951 |
| 1952 // TODO(jbramley): Is this load necessary? |
| 1953 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 1954 |
| 1955 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
| 1930 } | 1956 } |
| 1931 | 1957 |
| 1932 | 1958 |
| 1933 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { | |
| 1934 ASSERT(ToRegister(instr->result()).is(x0)); | |
| 1935 | |
| 1936 int arity = instr->arity(); | |
| 1937 Handle<Code> ic = | |
| 1938 isolate()->stub_cache()->ComputeCallInitialize(arity, CONTEXTUAL); | |
| 1939 __ Mov(x2, Operand(instr->name())); | |
| 1940 CallCode(ic, RelocInfo::CODE_TARGET, instr); | |
| 1941 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
| 1942 } | |
| 1943 | |
| 1944 | |
| 1945 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { | |
| 1946 ASSERT(ToRegister(instr->key()).Is(x2)); | |
| 1947 ASSERT(ToRegister(instr->result()).Is(x0)); | |
| 1948 | |
| 1949 int arity = instr->arity(); | |
| 1950 Handle<Code> ic = | |
| 1951 isolate()->stub_cache()->ComputeKeyedCallInitialize(arity); | |
| 1952 CallCode(ic, RelocInfo::CODE_TARGET, instr); | |
| 1953 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
| 1954 } | |
| 1955 | |
| 1956 | |
| 1957 void LCodeGen::DoCallNamed(LCallNamed* instr) { | |
| 1958 ASSERT(ToRegister(instr->result()).is(x0)); | |
| 1959 | |
| 1960 int arity = instr->arity(); | |
| 1961 Handle<Code> ic = | |
| 1962 isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_CONTEXTUAL); | |
| 1963 | |
| 1964 // IC needs a pointer to the name of the function to be called in x2. | |
| 1965 __ Mov(x2, Operand(instr->name())); | |
| 1966 CallCode(ic, RelocInfo::CODE_TARGET, instr); | |
| 1967 // Restore context register. | |
| 1968 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
| 1969 } | |
| 1970 | |
| 1971 | |
| 1972 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 1959 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
| 1973 CallRuntime(instr->function(), instr->arity(), instr); | 1960 CallRuntime(instr->function(), instr->arity(), instr); |
| 1974 } | 1961 } |
| 1975 | 1962 |
| 1976 | 1963 |
| 1977 void LCodeGen::DoCallStub(LCallStub* instr) { | 1964 void LCodeGen::DoCallStub(LCallStub* instr) { |
| 1978 ASSERT(ToRegister(instr->result()).is(x0)); | 1965 ASSERT(ToRegister(instr->result()).is(x0)); |
| 1979 switch (instr->hydrogen()->major_key()) { | 1966 switch (instr->hydrogen()->major_key()) { |
| 1980 case CodeStub::RegExpConstructResult: { | 1967 case CodeStub::RegExpConstructResult: { |
| 1981 RegExpConstructResultStub stub; | 1968 RegExpConstructResultStub stub; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2006 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 1993 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
| 2007 GenerateOsrPrologue(); | 1994 GenerateOsrPrologue(); |
| 2008 } | 1995 } |
| 2009 | 1996 |
| 2010 | 1997 |
| 2011 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { | 1998 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { |
| 2012 Register temp = ToRegister(instr->temp()); | 1999 Register temp = ToRegister(instr->temp()); |
| 2013 { | 2000 { |
| 2014 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 2001 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 2015 __ Push(object); | 2002 __ Push(object); |
| 2016 CallRuntimeFromDeferred(Runtime::kMigrateInstance, 1, instr); | 2003 CallRuntimeFromDeferred(Runtime::kTryMigrateInstance, 1, instr); |
| 2017 __ StoreToSafepointRegisterSlot(x0, temp); | 2004 __ StoreToSafepointRegisterSlot(x0, temp); |
| 2018 } | 2005 } |
| 2019 DeoptimizeIfSmi(temp, instr->environment()); | 2006 DeoptimizeIfSmi(temp, instr->environment()); |
| 2020 } | 2007 } |
| 2021 | 2008 |
| 2022 | 2009 |
| 2023 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { | 2010 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
| 2024 class DeferredCheckMaps: public LDeferredCode { | 2011 class DeferredCheckMaps: public LDeferredCode { |
| 2025 public: | 2012 public: |
| 2026 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) | 2013 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) |
| (...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2457 __ Cmp(reg, temp); | 2444 __ Cmp(reg, temp); |
| 2458 } else { | 2445 } else { |
| 2459 __ Cmp(reg, Operand(object)); | 2446 __ Cmp(reg, Operand(object)); |
| 2460 } | 2447 } |
| 2461 DeoptimizeIf(ne, instr->environment()); | 2448 DeoptimizeIf(ne, instr->environment()); |
| 2462 } | 2449 } |
| 2463 | 2450 |
| 2464 | 2451 |
| 2465 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { | 2452 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { |
| 2466 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | 2453 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
| 2467 last_lazy_deopt_pc_ = masm()->pc_offset(); | |
| 2468 ASSERT(instr->HasEnvironment()); | 2454 ASSERT(instr->HasEnvironment()); |
| 2469 LEnvironment* env = instr->environment(); | 2455 LEnvironment* env = instr->environment(); |
| 2470 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 2456 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); |
| 2471 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 2457 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
| 2472 } | 2458 } |
| 2473 | 2459 |
| 2474 | 2460 |
| 2475 void LCodeGen::DoDateField(LDateField* instr) { | 2461 void LCodeGen::DoDateField(LDateField* instr) { |
| 2476 Register object = ToRegister(instr->date()); | 2462 Register object = ToRegister(instr->date()); |
| 2477 Register result = ToRegister(instr->result()); | 2463 Register result = ToRegister(instr->result()); |
| (...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3059 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { | 3045 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
| 3060 // The function is required to be in x1. | 3046 // The function is required to be in x1. |
| 3061 ASSERT(ToRegister(instr->function()).is(x1)); | 3047 ASSERT(ToRegister(instr->function()).is(x1)); |
| 3062 ASSERT(instr->HasPointerMap()); | 3048 ASSERT(instr->HasPointerMap()); |
| 3063 | 3049 |
| 3064 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 3050 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); |
| 3065 if (known_function.is_null()) { | 3051 if (known_function.is_null()) { |
| 3066 LPointerMap* pointers = instr->pointer_map(); | 3052 LPointerMap* pointers = instr->pointer_map(); |
| 3067 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3053 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 3068 ParameterCount count(instr->arity()); | 3054 ParameterCount count(instr->arity()); |
| 3069 __ InvokeFunction(x1, count, CALL_FUNCTION, generator, CALL_AS_FUNCTION); | 3055 __ InvokeFunction(x1, count, CALL_FUNCTION, generator); |
| 3070 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3056 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 3071 } else { | 3057 } else { |
| 3072 CallKnownFunction(known_function, | 3058 CallKnownFunction(known_function, |
| 3073 instr->hydrogen()->formal_parameter_count(), | 3059 instr->hydrogen()->formal_parameter_count(), |
| 3074 instr->arity(), | 3060 instr->arity(), |
| 3075 instr, | 3061 instr, |
| 3076 CALL_AS_FUNCTION, | |
| 3077 x1); | 3062 x1); |
| 3078 } | 3063 } |
| 3079 } | 3064 } |
| 3080 | 3065 |
| 3081 | 3066 |
| 3082 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { | 3067 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
| 3083 Register temp1 = ToRegister(instr->temp1()); | 3068 Register temp1 = ToRegister(instr->temp1()); |
| 3084 Register temp2 = ToRegister(instr->temp2()); | 3069 Register temp2 = ToRegister(instr->temp2()); |
| 3085 | 3070 |
| 3086 // Get the frame pointer for the calling frame. | 3071 // Get the frame pointer for the calling frame. |
| (...skipping 1595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4682 ASSERT(instr->HasEnvironment()); | 4667 ASSERT(instr->HasEnvironment()); |
| 4683 LEnvironment* env = instr->environment(); | 4668 LEnvironment* env = instr->environment(); |
| 4684 // There is no LLazyBailout instruction for stack-checks. We have to | 4669 // There is no LLazyBailout instruction for stack-checks. We have to |
| 4685 // prepare for lazy deoptimization explicitly here. | 4670 // prepare for lazy deoptimization explicitly here. |
| 4686 if (instr->hydrogen()->is_function_entry()) { | 4671 if (instr->hydrogen()->is_function_entry()) { |
| 4687 // Perform stack overflow check. | 4672 // Perform stack overflow check. |
| 4688 Label done; | 4673 Label done; |
| 4689 __ CompareRoot(masm()->StackPointer(), Heap::kStackLimitRootIndex); | 4674 __ CompareRoot(masm()->StackPointer(), Heap::kStackLimitRootIndex); |
| 4690 __ B(hs, &done); | 4675 __ B(hs, &done); |
| 4691 | 4676 |
| 4692 // TODO(bafsa): Make sure that the EnsureSpaceForLazyDeopt inside | |
| 4693 // CallCodeGeneric will not insert any nop while calling the stub by | |
| 4694 // inserting them now. The EnsureSpaceForLazyDeopt in CallCodeGeneric | |
| 4695 // will go away at some point during the rebase (r18642) so this will become | |
| 4696 // unecessary and should be removed at this point. | |
| 4697 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | |
| 4698 | |
| 4699 PredictableCodeSizeScope predictable(masm_, | 4677 PredictableCodeSizeScope predictable(masm_, |
| 4700 Assembler::kCallSizeWithRelocation); | 4678 Assembler::kCallSizeWithRelocation); |
| 4701 CallCode(isolate()->builtins()->StackCheck(), | 4679 CallCode(isolate()->builtins()->StackCheck(), |
| 4702 RelocInfo::CODE_TARGET, | 4680 RelocInfo::CODE_TARGET, |
| 4703 instr); | 4681 instr); |
| 4704 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | 4682 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
| 4705 last_lazy_deopt_pc_ = masm()->pc_offset(); | |
| 4706 | 4683 |
| 4707 __ Bind(&done); | 4684 __ Bind(&done); |
| 4708 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 4685 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); |
| 4709 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 4686 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
| 4710 } else { | 4687 } else { |
| 4711 ASSERT(instr->hydrogen()->is_backwards_branch()); | 4688 ASSERT(instr->hydrogen()->is_backwards_branch()); |
| 4712 // Perform stack overflow check if this goto needs it before jumping. | 4689 // Perform stack overflow check if this goto needs it before jumping. |
| 4713 DeferredStackCheck* deferred_stack_check = | 4690 DeferredStackCheck* deferred_stack_check = |
| 4714 new(zone()) DeferredStackCheck(this, instr); | 4691 new(zone()) DeferredStackCheck(this, instr); |
| 4715 __ CompareRoot(masm()->StackPointer(), Heap::kStackLimitRootIndex); | 4692 __ CompareRoot(masm()->StackPointer(), Heap::kStackLimitRootIndex); |
| 4716 __ B(lo, deferred_stack_check->entry()); | 4693 __ B(lo, deferred_stack_check->entry()); |
| 4717 | 4694 |
| 4718 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | 4695 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
| 4719 last_lazy_deopt_pc_ = masm()->pc_offset(); | |
| 4720 __ Bind(instr->done_label()); | 4696 __ Bind(instr->done_label()); |
| 4721 deferred_stack_check->SetExit(instr->done_label()); | 4697 deferred_stack_check->SetExit(instr->done_label()); |
| 4722 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 4698 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); |
| 4723 // Don't record a deoptimization index for the safepoint here. | 4699 // Don't record a deoptimization index for the safepoint here. |
| 4724 // This will be done explicitly when emitting call and the safepoint in | 4700 // This will be done explicitly when emitting call and the safepoint in |
| 4725 // the deferred code. | 4701 // the deferred code. |
| 4726 } | 4702 } |
| 4727 } | 4703 } |
| 4728 | 4704 |
| 4729 | 4705 |
| (...skipping 888 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5618 __ B(ge, &done); | 5594 __ B(ge, &done); |
| 5619 // Otherwise, fall through to deopt. | 5595 // Otherwise, fall through to deopt. |
| 5620 | 5596 |
| 5621 __ Bind(&deopt); | 5597 __ Bind(&deopt); |
| 5622 Deoptimize(instr->environment()); | 5598 Deoptimize(instr->environment()); |
| 5623 | 5599 |
| 5624 __ Bind(&global_object); | 5600 __ Bind(&global_object); |
| 5625 // We could load directly into the result register here, but the additional | 5601 // We could load directly into the result register here, but the additional |
| 5626 // branches required are likely to be more time consuming than one additional | 5602 // branches required are likely to be more time consuming than one additional |
| 5627 // move. | 5603 // move. |
| 5628 // TODO(jbramley): This looks broken on ARM. There, a Context::SlotOffset() is | |
| 5629 // passed into ContextOperand. | |
| 5630 __ Ldr(receiver, FieldMemOperand(function, JSFunction::kContextOffset)); | 5604 __ Ldr(receiver, FieldMemOperand(function, JSFunction::kContextOffset)); |
| 5631 __ Ldr(receiver, ContextMemOperand(receiver, Context::GLOBAL_OBJECT_INDEX)); | 5605 __ Ldr(receiver, ContextMemOperand(receiver, Context::GLOBAL_OBJECT_INDEX)); |
| 5632 __ Ldr(receiver, | 5606 __ Ldr(receiver, |
| 5633 FieldMemOperand(receiver, GlobalObject::kGlobalReceiverOffset)); | 5607 FieldMemOperand(receiver, GlobalObject::kGlobalReceiverOffset)); |
| 5634 | 5608 |
| 5635 __ Bind(&done); | 5609 __ Bind(&done); |
| 5636 __ Mov(result, receiver); | 5610 __ Mov(result, receiver); |
| 5637 } | 5611 } |
| 5638 | 5612 |
| 5639 | 5613 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 5657 __ Bind(&out_of_object); | 5631 __ Bind(&out_of_object); |
| 5658 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 5632 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
| 5659 // Index is equal to negated out of object property index plus 1. | 5633 // Index is equal to negated out of object property index plus 1. |
| 5660 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); | 5634 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); |
| 5661 __ Ldr(result, FieldMemOperand(result, | 5635 __ Ldr(result, FieldMemOperand(result, |
| 5662 FixedArray::kHeaderSize - kPointerSize)); | 5636 FixedArray::kHeaderSize - kPointerSize)); |
| 5663 __ Bind(&done); | 5637 __ Bind(&done); |
| 5664 } | 5638 } |
| 5665 | 5639 |
| 5666 } } // namespace v8::internal | 5640 } } // namespace v8::internal |
| OLD | NEW |