OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1846 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1857 } | 1857 } |
1858 | 1858 |
1859 | 1859 |
1860 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { | 1860 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { |
1861 Register result = ToRegister(instr->result()); | 1861 Register result = ToRegister(instr->result()); |
1862 Register map = ToRegister(instr->value()); | 1862 Register map = ToRegister(instr->value()); |
1863 __ EnumLength(result, map); | 1863 __ EnumLength(result, map); |
1864 } | 1864 } |
1865 | 1865 |
1866 | 1866 |
1867 void LCodeGen::DoElementsKind(LElementsKind* instr) { | |
1868 Register result = ToRegister(instr->result()); | |
1869 Register input = ToRegister(instr->value()); | |
1870 | |
1871 // Load map into |result|. | |
1872 __ ldr(result, FieldMemOperand(input, HeapObject::kMapOffset)); | |
1873 // Load the map's "bit field 2" into |result|. We only need the first byte, | |
1874 // but the following bit field extraction takes care of that anyway. | |
1875 __ ldr(result, FieldMemOperand(result, Map::kBitField2Offset)); | |
1876 // Retrieve elements_kind from bit field 2. | |
1877 __ ubfx(result, result, Map::kElementsKindShift, Map::kElementsKindBitCount); | |
1878 } | |
1879 | |
1880 | |
1881 void LCodeGen::DoValueOf(LValueOf* instr) { | |
1882 Register input = ToRegister(instr->value()); | |
1883 Register result = ToRegister(instr->result()); | |
1884 Register map = ToRegister(instr->temp()); | |
1885 Label done; | |
1886 | |
1887 if (!instr->hydrogen()->value()->IsHeapObject()) { | |
1888 // If the object is a smi return the object. | |
1889 __ SmiTst(input); | |
1890 __ Move(result, input, eq); | |
1891 __ b(eq, &done); | |
1892 } | |
1893 | |
1894 // If the object is not a value type, return the object. | |
1895 __ CompareObjectType(input, map, map, JS_VALUE_TYPE); | |
1896 __ Move(result, input, ne); | |
1897 __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset), eq); | |
1898 | |
1899 __ bind(&done); | |
1900 } | |
1901 | |
1902 | |
1903 void LCodeGen::DoDateField(LDateField* instr) { | 1867 void LCodeGen::DoDateField(LDateField* instr) { |
1904 Register object = ToRegister(instr->date()); | 1868 Register object = ToRegister(instr->date()); |
1905 Register result = ToRegister(instr->result()); | 1869 Register result = ToRegister(instr->result()); |
1906 Register scratch = ToRegister(instr->temp()); | 1870 Register scratch = ToRegister(instr->temp()); |
1907 Smi* index = instr->index(); | 1871 Smi* index = instr->index(); |
1908 Label runtime, done; | 1872 Label runtime, done; |
1909 ASSERT(object.is(result)); | 1873 ASSERT(object.is(result)); |
1910 ASSERT(object.is(r0)); | 1874 ASSERT(object.is(r0)); |
1911 ASSERT(!scratch.is(scratch0())); | 1875 ASSERT(!scratch.is(scratch0())); |
1912 ASSERT(!scratch.is(object)); | 1876 ASSERT(!scratch.is(object)); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2008 | 1972 |
2009 MemOperand operand = BuildSeqStringOperand(string, instr->index(), encoding); | 1973 MemOperand operand = BuildSeqStringOperand(string, instr->index(), encoding); |
2010 if (encoding == String::ONE_BYTE_ENCODING) { | 1974 if (encoding == String::ONE_BYTE_ENCODING) { |
2011 __ strb(value, operand); | 1975 __ strb(value, operand); |
2012 } else { | 1976 } else { |
2013 __ strh(value, operand); | 1977 __ strh(value, operand); |
2014 } | 1978 } |
2015 } | 1979 } |
2016 | 1980 |
2017 | 1981 |
2018 void LCodeGen::DoThrow(LThrow* instr) { | |
2019 __ push(ToRegister(instr->value())); | |
2020 ASSERT(ToRegister(instr->context()).is(cp)); | |
2021 CallRuntime(Runtime::kThrow, 1, instr); | |
2022 | |
2023 if (FLAG_debug_code) { | |
2024 __ stop("Unreachable code."); | |
2025 } | |
2026 } | |
2027 | |
2028 | |
2029 void LCodeGen::DoAddI(LAddI* instr) { | 1982 void LCodeGen::DoAddI(LAddI* instr) { |
2030 LOperand* left = instr->left(); | 1983 LOperand* left = instr->left(); |
2031 LOperand* right = instr->right(); | 1984 LOperand* right = instr->right(); |
2032 LOperand* result = instr->result(); | 1985 LOperand* result = instr->result(); |
2033 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1986 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
2034 SBit set_cond = can_overflow ? SetCC : LeaveCC; | 1987 SBit set_cond = can_overflow ? SetCC : LeaveCC; |
2035 | 1988 |
2036 if (right->IsStackSlot() || right->IsArgument()) { | 1989 if (right->IsStackSlot() || right->IsArgument()) { |
2037 Register right_reg = EmitLoadRegister(right, ip); | 1990 Register right_reg = EmitLoadRegister(right, ip); |
2038 __ add(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); | 1991 __ add(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); |
(...skipping 1430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3469 Register receiver = ToRegister(instr->receiver()); | 3422 Register receiver = ToRegister(instr->receiver()); |
3470 Register function = ToRegister(instr->function()); | 3423 Register function = ToRegister(instr->function()); |
3471 Register result = ToRegister(instr->result()); | 3424 Register result = ToRegister(instr->result()); |
3472 Register scratch = scratch0(); | 3425 Register scratch = scratch0(); |
3473 | 3426 |
3474 // If the receiver is null or undefined, we have to pass the global | 3427 // If the receiver is null or undefined, we have to pass the global |
3475 // object as a receiver to normal functions. Values have to be | 3428 // object as a receiver to normal functions. Values have to be |
3476 // passed unchanged to builtins and strict-mode functions. | 3429 // passed unchanged to builtins and strict-mode functions. |
3477 Label global_object, result_in_receiver; | 3430 Label global_object, result_in_receiver; |
3478 | 3431 |
3479 // Do not transform the receiver to object for strict mode | 3432 if (!instr->hydrogen()->known_function()) { |
3480 // functions. | 3433 // Do not transform the receiver to object for strict mode |
3481 __ ldr(scratch, | 3434 // functions. |
3482 FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset)); | 3435 __ ldr(scratch, |
3483 __ ldr(scratch, | 3436 FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset)); |
3484 FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset)); | 3437 __ ldr(scratch, |
3485 __ tst(scratch, | 3438 FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset)); |
3486 Operand(1 << (SharedFunctionInfo::kStrictModeFunction + kSmiTagSize))); | 3439 int mask = 1 << (SharedFunctionInfo::kStrictModeFunction + kSmiTagSize); |
3487 __ b(ne, &result_in_receiver); | 3440 __ tst(scratch, Operand(mask)); |
| 3441 __ b(ne, &result_in_receiver); |
3488 | 3442 |
3489 // Do not transform the receiver to object for builtins. | 3443 // Do not transform the receiver to object for builtins. |
3490 __ tst(scratch, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize))); | 3444 __ tst(scratch, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize))); |
3491 __ b(ne, &result_in_receiver); | 3445 __ b(ne, &result_in_receiver); |
| 3446 } |
3492 | 3447 |
3493 // Normal function. Replace undefined or null with global receiver. | 3448 // Normal function. Replace undefined or null with global receiver. |
3494 __ LoadRoot(scratch, Heap::kNullValueRootIndex); | 3449 __ LoadRoot(scratch, Heap::kNullValueRootIndex); |
3495 __ cmp(receiver, scratch); | 3450 __ cmp(receiver, scratch); |
3496 __ b(eq, &global_object); | 3451 __ b(eq, &global_object); |
3497 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); | 3452 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); |
3498 __ cmp(receiver, scratch); | 3453 __ cmp(receiver, scratch); |
3499 __ b(eq, &global_object); | 3454 __ b(eq, &global_object); |
3500 | 3455 |
3501 // Deoptimize if the receiver is not a JS object. | 3456 // Deoptimize if the receiver is not a JS object. |
3502 __ SmiTst(receiver); | 3457 __ SmiTst(receiver); |
3503 DeoptimizeIf(eq, instr->environment()); | 3458 DeoptimizeIf(eq, instr->environment()); |
3504 __ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE); | 3459 __ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE); |
3505 DeoptimizeIf(lt, instr->environment()); | 3460 DeoptimizeIf(lt, instr->environment()); |
| 3461 |
3506 __ b(&result_in_receiver); | 3462 __ b(&result_in_receiver); |
3507 | |
3508 __ bind(&global_object); | 3463 __ bind(&global_object); |
3509 __ ldr(result, FieldMemOperand(function, JSFunction::kContextOffset)); | 3464 __ ldr(result, FieldMemOperand(function, JSFunction::kContextOffset)); |
3510 __ ldr(result, | 3465 __ ldr(result, |
3511 ContextOperand(result, Context::GLOBAL_OBJECT_INDEX)); | 3466 ContextOperand(result, Context::GLOBAL_OBJECT_INDEX)); |
3512 __ ldr(result, | 3467 __ ldr(result, |
3513 FieldMemOperand(result, GlobalObject::kGlobalReceiverOffset)); | 3468 FieldMemOperand(result, GlobalObject::kGlobalReceiverOffset)); |
3514 | 3469 |
3515 if (result.is(receiver)) { | 3470 if (result.is(receiver)) { |
3516 __ bind(&result_in_receiver); | 3471 __ bind(&result_in_receiver); |
3517 } else { | 3472 } else { |
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3984 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 3939 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
3985 } | 3940 } |
3986 | 3941 |
3987 | 3942 |
3988 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 3943 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
3989 ASSERT(ToRegister(instr->context()).is(cp)); | 3944 ASSERT(ToRegister(instr->context()).is(cp)); |
3990 ASSERT(ToRegister(instr->function()).is(r1)); | 3945 ASSERT(ToRegister(instr->function()).is(r1)); |
3991 ASSERT(ToRegister(instr->result()).is(r0)); | 3946 ASSERT(ToRegister(instr->result()).is(r0)); |
3992 | 3947 |
3993 int arity = instr->arity(); | 3948 int arity = instr->arity(); |
3994 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); | 3949 CallFunctionStub stub(arity, instr->hydrogen()->function_flags()); |
3995 if (instr->hydrogen()->IsTailCall()) { | 3950 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
3996 if (NeedsEagerFrame()) __ mov(sp, fp); | |
3997 __ Jump(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); | |
3998 } else { | |
3999 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | |
4000 } | |
4001 } | 3951 } |
4002 | 3952 |
4003 | 3953 |
4004 void LCodeGen::DoCallNew(LCallNew* instr) { | 3954 void LCodeGen::DoCallNew(LCallNew* instr) { |
4005 ASSERT(ToRegister(instr->context()).is(cp)); | 3955 ASSERT(ToRegister(instr->context()).is(cp)); |
4006 ASSERT(ToRegister(instr->constructor()).is(r1)); | 3956 ASSERT(ToRegister(instr->constructor()).is(r1)); |
4007 ASSERT(ToRegister(instr->result()).is(r0)); | 3957 ASSERT(ToRegister(instr->result()).is(r0)); |
4008 | 3958 |
4009 __ mov(r0, Operand(instr->arity())); | 3959 __ mov(r0, Operand(instr->arity())); |
4010 // No cell in r2 for construct type feedback in optimized code | 3960 // No cell in r2 for construct type feedback in optimized code |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4101 } | 4051 } |
4102 | 4052 |
4103 Handle<Map> transition = instr->transition(); | 4053 Handle<Map> transition = instr->transition(); |
4104 | 4054 |
4105 if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { | 4055 if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { |
4106 Register value = ToRegister(instr->value()); | 4056 Register value = ToRegister(instr->value()); |
4107 if (!instr->hydrogen()->value()->type().IsHeapObject()) { | 4057 if (!instr->hydrogen()->value()->type().IsHeapObject()) { |
4108 __ SmiTst(value); | 4058 __ SmiTst(value); |
4109 DeoptimizeIf(eq, instr->environment()); | 4059 DeoptimizeIf(eq, instr->environment()); |
4110 } | 4060 } |
4111 } else if (FLAG_track_double_fields && representation.IsDouble()) { | 4061 } else if (representation.IsDouble()) { |
4112 ASSERT(transition.is_null()); | 4062 ASSERT(transition.is_null()); |
4113 ASSERT(access.IsInobject()); | 4063 ASSERT(access.IsInobject()); |
4114 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); | 4064 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); |
4115 DwVfpRegister value = ToDoubleRegister(instr->value()); | 4065 DwVfpRegister value = ToDoubleRegister(instr->value()); |
4116 __ vstr(value, FieldMemOperand(object, offset)); | 4066 __ vstr(value, FieldMemOperand(object, offset)); |
4117 return; | 4067 return; |
4118 } | 4068 } |
4119 | 4069 |
4120 if (!transition.is_null()) { | 4070 if (!transition.is_null()) { |
4121 __ mov(scratch, Operand(transition)); | 4071 __ mov(scratch, Operand(transition)); |
(...skipping 1668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5790 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); | 5740 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); |
5791 __ ldr(result, FieldMemOperand(scratch, | 5741 __ ldr(result, FieldMemOperand(scratch, |
5792 FixedArray::kHeaderSize - kPointerSize)); | 5742 FixedArray::kHeaderSize - kPointerSize)); |
5793 __ bind(&done); | 5743 __ bind(&done); |
5794 } | 5744 } |
5795 | 5745 |
5796 | 5746 |
5797 #undef __ | 5747 #undef __ |
5798 | 5748 |
5799 } } // namespace v8::internal | 5749 } } // namespace v8::internal |
OLD | NEW |