| 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 |