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 1950 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1961 } | 1961 } |
1962 | 1962 |
1963 | 1963 |
1964 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { | 1964 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { |
1965 Register result = ToRegister(instr->result()); | 1965 Register result = ToRegister(instr->result()); |
1966 Register map = ToRegister(instr->value()); | 1966 Register map = ToRegister(instr->value()); |
1967 __ EnumLength(result, map); | 1967 __ EnumLength(result, map); |
1968 } | 1968 } |
1969 | 1969 |
1970 | 1970 |
1971 void LCodeGen::DoElementsKind(LElementsKind* instr) { | |
1972 Register result = ToRegister(instr->result()); | |
1973 Register input = ToRegister(instr->value()); | |
1974 | |
1975 // Load map into |result|. | |
1976 __ mov(result, FieldOperand(input, HeapObject::kMapOffset)); | |
1977 // Load the map's "bit field 2" into |result|. We only need the first byte, | |
1978 // but the following masking takes care of that anyway. | |
1979 __ mov(result, FieldOperand(result, Map::kBitField2Offset)); | |
1980 // Retrieve elements_kind from bit field 2. | |
1981 __ and_(result, Map::kElementsKindMask); | |
1982 __ shr(result, Map::kElementsKindShift); | |
1983 } | |
1984 | |
1985 | |
1986 void LCodeGen::DoValueOf(LValueOf* instr) { | |
1987 Register input = ToRegister(instr->value()); | |
1988 Register result = ToRegister(instr->result()); | |
1989 Register map = ToRegister(instr->temp()); | |
1990 ASSERT(input.is(result)); | |
1991 | |
1992 Label done; | |
1993 | |
1994 if (!instr->hydrogen()->value()->IsHeapObject()) { | |
1995 // If the object is a smi return the object. | |
1996 __ JumpIfSmi(input, &done, Label::kNear); | |
1997 } | |
1998 | |
1999 // If the object is not a value type, return the object. | |
2000 __ CmpObjectType(input, JS_VALUE_TYPE, map); | |
2001 __ j(not_equal, &done, Label::kNear); | |
2002 __ mov(result, FieldOperand(input, JSValue::kValueOffset)); | |
2003 | |
2004 __ bind(&done); | |
2005 } | |
2006 | |
2007 | |
2008 void LCodeGen::DoDateField(LDateField* instr) { | 1971 void LCodeGen::DoDateField(LDateField* instr) { |
2009 Register object = ToRegister(instr->date()); | 1972 Register object = ToRegister(instr->date()); |
2010 Register result = ToRegister(instr->result()); | 1973 Register result = ToRegister(instr->result()); |
2011 Register scratch = ToRegister(instr->temp()); | 1974 Register scratch = ToRegister(instr->temp()); |
2012 Smi* index = instr->index(); | 1975 Smi* index = instr->index(); |
2013 Label runtime, done; | 1976 Label runtime, done; |
2014 ASSERT(object.is(result)); | 1977 ASSERT(object.is(result)); |
2015 ASSERT(object.is(eax)); | 1978 ASSERT(object.is(eax)); |
2016 | 1979 |
2017 __ test(object, Immediate(kSmiTagMask)); | 1980 __ test(object, Immediate(kSmiTagMask)); |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2119 Register value = ToRegister(instr->value()); | 2082 Register value = ToRegister(instr->value()); |
2120 if (encoding == String::ONE_BYTE_ENCODING) { | 2083 if (encoding == String::ONE_BYTE_ENCODING) { |
2121 __ mov_b(operand, value); | 2084 __ mov_b(operand, value); |
2122 } else { | 2085 } else { |
2123 __ mov_w(operand, value); | 2086 __ mov_w(operand, value); |
2124 } | 2087 } |
2125 } | 2088 } |
2126 } | 2089 } |
2127 | 2090 |
2128 | 2091 |
2129 void LCodeGen::DoThrow(LThrow* instr) { | |
2130 __ push(ToOperand(instr->value())); | |
2131 ASSERT(ToRegister(instr->context()).is(esi)); | |
2132 CallRuntime(Runtime::kThrow, 1, instr); | |
2133 | |
2134 if (FLAG_debug_code) { | |
2135 Comment("Unreachable code."); | |
2136 __ int3(); | |
2137 } | |
2138 } | |
2139 | |
2140 | |
2141 void LCodeGen::DoAddI(LAddI* instr) { | 2092 void LCodeGen::DoAddI(LAddI* instr) { |
2142 LOperand* left = instr->left(); | 2093 LOperand* left = instr->left(); |
2143 LOperand* right = instr->right(); | 2094 LOperand* right = instr->right(); |
2144 | 2095 |
2145 if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) { | 2096 if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) { |
2146 if (right->IsConstantOperand()) { | 2097 if (right->IsConstantOperand()) { |
2147 int32_t offset = ToRepresentation(LConstantOperand::cast(right), | 2098 int32_t offset = ToRepresentation(LConstantOperand::cast(right), |
2148 instr->hydrogen()->representation()); | 2099 instr->hydrogen()->representation()); |
2149 __ lea(ToRegister(instr->result()), MemOperand(ToRegister(left), offset)); | 2100 __ lea(ToRegister(instr->result()), MemOperand(ToRegister(left), offset)); |
2150 } else { | 2101 } else { |
(...skipping 1104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3255 Register result = ToRegister(instr->result()); | 3206 Register result = ToRegister(instr->result()); |
3256 MemOperand operand = instr->object()->IsConstantOperand() | 3207 MemOperand operand = instr->object()->IsConstantOperand() |
3257 ? MemOperand::StaticVariable(ToExternalReference( | 3208 ? MemOperand::StaticVariable(ToExternalReference( |
3258 LConstantOperand::cast(instr->object()))) | 3209 LConstantOperand::cast(instr->object()))) |
3259 : MemOperand(ToRegister(instr->object()), offset); | 3210 : MemOperand(ToRegister(instr->object()), offset); |
3260 __ Load(result, operand, access.representation()); | 3211 __ Load(result, operand, access.representation()); |
3261 return; | 3212 return; |
3262 } | 3213 } |
3263 | 3214 |
3264 Register object = ToRegister(instr->object()); | 3215 Register object = ToRegister(instr->object()); |
3265 if (FLAG_track_double_fields && | 3216 if (instr->hydrogen()->representation().IsDouble()) { |
3266 instr->hydrogen()->representation().IsDouble()) { | |
3267 if (CpuFeatures::IsSupported(SSE2)) { | 3217 if (CpuFeatures::IsSupported(SSE2)) { |
3268 CpuFeatureScope scope(masm(), SSE2); | 3218 CpuFeatureScope scope(masm(), SSE2); |
3269 XMMRegister result = ToDoubleRegister(instr->result()); | 3219 XMMRegister result = ToDoubleRegister(instr->result()); |
3270 __ movsd(result, FieldOperand(object, offset)); | 3220 __ movsd(result, FieldOperand(object, offset)); |
3271 } else { | 3221 } else { |
3272 X87Mov(ToX87Register(instr->result()), FieldOperand(object, offset)); | 3222 X87Mov(ToX87Register(instr->result()), FieldOperand(object, offset)); |
3273 } | 3223 } |
3274 return; | 3224 return; |
3275 } | 3225 } |
3276 | 3226 |
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3624 __ SmiUntag(result); | 3574 __ SmiUntag(result); |
3625 | 3575 |
3626 // Argument length is in result register. | 3576 // Argument length is in result register. |
3627 __ bind(&done); | 3577 __ bind(&done); |
3628 } | 3578 } |
3629 | 3579 |
3630 | 3580 |
3631 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { | 3581 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { |
3632 Register receiver = ToRegister(instr->receiver()); | 3582 Register receiver = ToRegister(instr->receiver()); |
3633 Register function = ToRegister(instr->function()); | 3583 Register function = ToRegister(instr->function()); |
3634 Register scratch = ToRegister(instr->temp()); | |
3635 | 3584 |
3636 // If the receiver is null or undefined, we have to pass the global | 3585 // If the receiver is null or undefined, we have to pass the global |
3637 // object as a receiver to normal functions. Values have to be | 3586 // object as a receiver to normal functions. Values have to be |
3638 // passed unchanged to builtins and strict-mode functions. | 3587 // passed unchanged to builtins and strict-mode functions. |
3639 Label receiver_ok, global_object; | 3588 Label receiver_ok, global_object; |
3640 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; | 3589 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; |
| 3590 Register scratch = ToRegister(instr->temp()); |
3641 | 3591 |
3642 // Do not transform the receiver to object for strict mode | 3592 if (!instr->hydrogen()->known_function()) { |
3643 // functions. | 3593 // Do not transform the receiver to object for strict mode |
3644 __ mov(scratch, | 3594 // functions. |
3645 FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); | 3595 __ mov(scratch, |
3646 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset), | 3596 FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); |
3647 1 << SharedFunctionInfo::kStrictModeBitWithinByte); | 3597 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset), |
3648 __ j(not_equal, &receiver_ok, dist); | 3598 1 << SharedFunctionInfo::kStrictModeBitWithinByte); |
| 3599 __ j(not_equal, &receiver_ok, dist); |
3649 | 3600 |
3650 // Do not transform the receiver to object for builtins. | 3601 // Do not transform the receiver to object for builtins. |
3651 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset), | 3602 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset), |
3652 1 << SharedFunctionInfo::kNativeBitWithinByte); | 3603 1 << SharedFunctionInfo::kNativeBitWithinByte); |
3653 __ j(not_equal, &receiver_ok, dist); | 3604 __ j(not_equal, &receiver_ok, dist); |
| 3605 } |
3654 | 3606 |
3655 // Normal function. Replace undefined or null with global receiver. | 3607 // Normal function. Replace undefined or null with global receiver. |
3656 __ cmp(receiver, factory()->null_value()); | 3608 __ cmp(receiver, factory()->null_value()); |
3657 __ j(equal, &global_object, Label::kNear); | 3609 __ j(equal, &global_object, Label::kNear); |
3658 __ cmp(receiver, factory()->undefined_value()); | 3610 __ cmp(receiver, factory()->undefined_value()); |
3659 __ j(equal, &global_object, Label::kNear); | 3611 __ j(equal, &global_object, Label::kNear); |
3660 | 3612 |
3661 // The receiver should be a JS object. | 3613 // The receiver should be a JS object. |
3662 __ test(receiver, Immediate(kSmiTagMask)); | 3614 __ test(receiver, Immediate(kSmiTagMask)); |
3663 DeoptimizeIf(equal, instr->environment()); | 3615 DeoptimizeIf(equal, instr->environment()); |
3664 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch); | 3616 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch); |
3665 DeoptimizeIf(below, instr->environment()); | 3617 DeoptimizeIf(below, instr->environment()); |
| 3618 |
3666 __ jmp(&receiver_ok, Label::kNear); | 3619 __ jmp(&receiver_ok, Label::kNear); |
3667 | |
3668 __ bind(&global_object); | 3620 __ bind(&global_object); |
3669 __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset)); | 3621 __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset)); |
3670 __ mov(receiver, | 3622 const int global_offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); |
3671 Operand(receiver, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 3623 __ mov(receiver, Operand(receiver, global_offset)); |
3672 __ mov(receiver, FieldOperand(receiver, GlobalObject::kGlobalReceiverOffset)); | 3624 const int receiver_offset = GlobalObject::kGlobalReceiverOffset; |
3673 | 3625 __ mov(receiver, FieldOperand(receiver, receiver_offset)); |
3674 __ bind(&receiver_ok); | 3626 __ bind(&receiver_ok); |
3675 } | 3627 } |
3676 | 3628 |
3677 | 3629 |
3678 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { | 3630 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { |
3679 Register receiver = ToRegister(instr->receiver()); | 3631 Register receiver = ToRegister(instr->receiver()); |
3680 Register function = ToRegister(instr->function()); | 3632 Register function = ToRegister(instr->function()); |
3681 Register length = ToRegister(instr->length()); | 3633 Register length = ToRegister(instr->length()); |
3682 Register elements = ToRegister(instr->elements()); | 3634 Register elements = ToRegister(instr->elements()); |
3683 ASSERT(receiver.is(eax)); // Used for parameter count. | 3635 ASSERT(receiver.is(eax)); // Used for parameter count. |
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4217 } | 4169 } |
4218 } | 4170 } |
4219 | 4171 |
4220 | 4172 |
4221 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 4173 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
4222 ASSERT(ToRegister(instr->context()).is(esi)); | 4174 ASSERT(ToRegister(instr->context()).is(esi)); |
4223 ASSERT(ToRegister(instr->function()).is(edi)); | 4175 ASSERT(ToRegister(instr->function()).is(edi)); |
4224 ASSERT(ToRegister(instr->result()).is(eax)); | 4176 ASSERT(ToRegister(instr->result()).is(eax)); |
4225 | 4177 |
4226 int arity = instr->arity(); | 4178 int arity = instr->arity(); |
4227 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); | 4179 CallFunctionStub stub(arity, instr->hydrogen()->function_flags()); |
4228 if (instr->hydrogen()->IsTailCall()) { | 4180 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
4229 if (NeedsEagerFrame()) __ leave(); | |
4230 __ jmp(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); | |
4231 } else { | |
4232 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | |
4233 } | |
4234 } | 4181 } |
4235 | 4182 |
4236 | 4183 |
4237 void LCodeGen::DoCallNew(LCallNew* instr) { | 4184 void LCodeGen::DoCallNew(LCallNew* instr) { |
4238 ASSERT(ToRegister(instr->context()).is(esi)); | 4185 ASSERT(ToRegister(instr->context()).is(esi)); |
4239 ASSERT(ToRegister(instr->constructor()).is(edi)); | 4186 ASSERT(ToRegister(instr->constructor()).is(edi)); |
4240 ASSERT(ToRegister(instr->result()).is(eax)); | 4187 ASSERT(ToRegister(instr->result()).is(eax)); |
4241 | 4188 |
4242 // No cell in ebx for construct type feedback in optimized code | 4189 // No cell in ebx for construct type feedback in optimized code |
4243 Handle<Object> undefined_value(isolate()->factory()->undefined_value()); | 4190 Handle<Object> undefined_value(isolate()->factory()->undefined_value()); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4356 if (IsInteger32(operand_value)) { | 4303 if (IsInteger32(operand_value)) { |
4357 DeoptimizeIf(no_condition, instr->environment()); | 4304 DeoptimizeIf(no_condition, instr->environment()); |
4358 } | 4305 } |
4359 } else { | 4306 } else { |
4360 if (!instr->hydrogen()->value()->type().IsHeapObject()) { | 4307 if (!instr->hydrogen()->value()->type().IsHeapObject()) { |
4361 Register value = ToRegister(instr->value()); | 4308 Register value = ToRegister(instr->value()); |
4362 __ test(value, Immediate(kSmiTagMask)); | 4309 __ test(value, Immediate(kSmiTagMask)); |
4363 DeoptimizeIf(zero, instr->environment()); | 4310 DeoptimizeIf(zero, instr->environment()); |
4364 } | 4311 } |
4365 } | 4312 } |
4366 } else if (FLAG_track_double_fields && representation.IsDouble()) { | 4313 } else if (representation.IsDouble()) { |
4367 ASSERT(transition.is_null()); | 4314 ASSERT(transition.is_null()); |
4368 ASSERT(access.IsInobject()); | 4315 ASSERT(access.IsInobject()); |
4369 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); | 4316 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); |
4370 if (CpuFeatures::IsSupported(SSE2)) { | 4317 if (CpuFeatures::IsSupported(SSE2)) { |
4371 CpuFeatureScope scope(masm(), SSE2); | 4318 CpuFeatureScope scope(masm(), SSE2); |
4372 XMMRegister value = ToDoubleRegister(instr->value()); | 4319 XMMRegister value = ToDoubleRegister(instr->value()); |
4373 __ movsd(FieldOperand(object, offset), value); | 4320 __ movsd(FieldOperand(object, offset), value); |
4374 } else { | 4321 } else { |
4375 X87Register value = ToX87Register(instr->value()); | 4322 X87Register value = ToX87Register(instr->value()); |
4376 X87Mov(FieldOperand(object, offset), value); | 4323 X87Mov(FieldOperand(object, offset), value); |
(...skipping 1942 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6319 FixedArray::kHeaderSize - kPointerSize)); | 6266 FixedArray::kHeaderSize - kPointerSize)); |
6320 __ bind(&done); | 6267 __ bind(&done); |
6321 } | 6268 } |
6322 | 6269 |
6323 | 6270 |
6324 #undef __ | 6271 #undef __ |
6325 | 6272 |
6326 } } // namespace v8::internal | 6273 } } // namespace v8::internal |
6327 | 6274 |
6328 #endif // V8_TARGET_ARCH_IA32 | 6275 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |