Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(244)

Side by Side Diff: src/ia32/lithium-codegen-ia32.cc

Issue 8404030: Version 3.7.1 (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-ia32.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 348
349 int LCodeGen::ToInteger32(LConstantOperand* op) const { 349 int LCodeGen::ToInteger32(LConstantOperand* op) const {
350 Handle<Object> value = chunk_->LookupLiteral(op); 350 Handle<Object> value = chunk_->LookupLiteral(op);
351 ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32()); 351 ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32());
352 ASSERT(static_cast<double>(static_cast<int32_t>(value->Number())) == 352 ASSERT(static_cast<double>(static_cast<int32_t>(value->Number())) ==
353 value->Number()); 353 value->Number());
354 return static_cast<int32_t>(value->Number()); 354 return static_cast<int32_t>(value->Number());
355 } 355 }
356 356
357 357
358 double LCodeGen::ToDouble(LConstantOperand* op) const {
359 Handle<Object> value = chunk_->LookupLiteral(op);
360 return value->Number();
361 }
362
363
358 Immediate LCodeGen::ToImmediate(LOperand* op) { 364 Immediate LCodeGen::ToImmediate(LOperand* op) {
359 LConstantOperand* const_op = LConstantOperand::cast(op); 365 LConstantOperand* const_op = LConstantOperand::cast(op);
360 Handle<Object> literal = chunk_->LookupLiteral(const_op); 366 Handle<Object> literal = chunk_->LookupLiteral(const_op);
361 Representation r = chunk_->LookupLiteralRepresentation(const_op); 367 Representation r = chunk_->LookupLiteralRepresentation(const_op);
362 if (r.IsInteger32()) { 368 if (r.IsInteger32()) {
363 ASSERT(literal->IsNumber()); 369 ASSERT(literal->IsNumber());
364 return Immediate(static_cast<int32_t>(literal->Number())); 370 return Immediate(static_cast<int32_t>(literal->Number()));
365 } else if (r.IsDouble()) { 371 } else if (r.IsDouble()) {
366 Abort("unsupported double immediate"); 372 Abort("unsupported double immediate");
367 } 373 }
(...skipping 1199 matching lines...) Expand 10 before | Expand all | Expand 10 after
1567 break; 1573 break;
1568 case Token::IN: 1574 case Token::IN:
1569 case Token::INSTANCEOF: 1575 case Token::INSTANCEOF:
1570 default: 1576 default:
1571 UNREACHABLE(); 1577 UNREACHABLE();
1572 } 1578 }
1573 return cond; 1579 return cond;
1574 } 1580 }
1575 1581
1576 1582
1577 void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) {
1578 if (right->IsConstantOperand()) {
1579 __ cmp(ToOperand(left), ToImmediate(right));
1580 } else {
1581 __ cmp(ToRegister(left), ToOperand(right));
1582 }
1583 }
1584
1585
1586 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { 1583 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
1587 LOperand* left = instr->InputAt(0); 1584 LOperand* left = instr->InputAt(0);
1588 LOperand* right = instr->InputAt(1); 1585 LOperand* right = instr->InputAt(1);
1589 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1586 int false_block = chunk_->LookupDestination(instr->false_block_id());
1590 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1587 int true_block = chunk_->LookupDestination(instr->true_block_id());
1588 Condition cc = TokenToCondition(instr->op(), instr->is_double());
1591 1589
1592 if (instr->is_double()) { 1590 if (left->IsConstantOperand() && right->IsConstantOperand()) {
1593 // Don't base result on EFLAGS when a NaN is involved. Instead 1591 // We can statically evaluate the comparison.
1594 // jump to the false block. 1592 double left_val = ToDouble(LConstantOperand::cast(left));
1595 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); 1593 double right_val = ToDouble(LConstantOperand::cast(right));
1596 __ j(parity_even, chunk_->GetAssemblyLabel(false_block)); 1594 int next_block =
1595 EvalComparison(instr->op(), left_val, right_val) ? true_block
1596 : false_block;
1597 EmitGoto(next_block);
1597 } else { 1598 } else {
1598 EmitCmpI(left, right); 1599 if (instr->is_double()) {
1600 // Don't base result on EFLAGS when a NaN is involved. Instead
1601 // jump to the false block.
1602 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
1603 __ j(parity_even, chunk_->GetAssemblyLabel(false_block));
1604 } else {
1605 if (right->IsConstantOperand()) {
1606 __ cmp(ToRegister(left), ToImmediate(right));
1607 } else if (left->IsConstantOperand()) {
1608 __ cmp(ToOperand(right), ToImmediate(left));
1609 // We transposed the operands. Reverse the condition.
1610 cc = ReverseCondition(cc);
1611 } else {
1612 __ cmp(ToRegister(left), ToOperand(right));
1613 }
1614 }
1615 EmitBranch(true_block, false_block, cc);
1599 } 1616 }
1600
1601 Condition cc = TokenToCondition(instr->op(), instr->is_double());
1602 EmitBranch(true_block, false_block, cc);
1603 } 1617 }
1604 1618
1605 1619
1606 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { 1620 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
1607 Register left = ToRegister(instr->InputAt(0)); 1621 Register left = ToRegister(instr->InputAt(0));
1608 Operand right = ToOperand(instr->InputAt(1)); 1622 Operand right = ToOperand(instr->InputAt(1));
1609 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1623 int false_block = chunk_->LookupDestination(instr->false_block_id());
1610 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1624 int true_block = chunk_->LookupDestination(instr->true_block_id());
1611 1625
1612 __ cmp(left, Operand(right)); 1626 __ cmp(left, Operand(right));
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after
2022 } 2036 }
2023 2037
2024 2038
2025 void LCodeGen::DoCmpT(LCmpT* instr) { 2039 void LCodeGen::DoCmpT(LCmpT* instr) {
2026 Token::Value op = instr->op(); 2040 Token::Value op = instr->op();
2027 2041
2028 Handle<Code> ic = CompareIC::GetUninitialized(op); 2042 Handle<Code> ic = CompareIC::GetUninitialized(op);
2029 CallCode(ic, RelocInfo::CODE_TARGET, instr); 2043 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2030 2044
2031 Condition condition = ComputeCompareCondition(op); 2045 Condition condition = ComputeCompareCondition(op);
2032 if (op == Token::GT || op == Token::LTE) {
2033 condition = ReverseCondition(condition);
2034 }
2035 Label true_value, done; 2046 Label true_value, done;
2036 __ test(eax, Operand(eax)); 2047 __ test(eax, Operand(eax));
2037 __ j(condition, &true_value, Label::kNear); 2048 __ j(condition, &true_value, Label::kNear);
2038 __ mov(ToRegister(instr->result()), factory()->false_value()); 2049 __ mov(ToRegister(instr->result()), factory()->false_value());
2039 __ jmp(&done, Label::kNear); 2050 __ jmp(&done, Label::kNear);
2040 __ bind(&true_value); 2051 __ bind(&true_value);
2041 __ mov(ToRegister(instr->result()), factory()->true_value()); 2052 __ mov(ToRegister(instr->result()), factory()->true_value());
2042 __ bind(&done); 2053 __ bind(&done);
2043 } 2054 }
2044 2055
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
2109 // it as no longer deleted. We deoptimize in that case. 2120 // it as no longer deleted. We deoptimize in that case.
2110 if (instr->hydrogen()->RequiresHoleCheck()) { 2121 if (instr->hydrogen()->RequiresHoleCheck()) {
2111 __ cmp(FieldOperand(object, offset), factory()->the_hole_value()); 2122 __ cmp(FieldOperand(object, offset), factory()->the_hole_value());
2112 DeoptimizeIf(equal, instr->environment()); 2123 DeoptimizeIf(equal, instr->environment());
2113 } 2124 }
2114 2125
2115 // Store the value. 2126 // Store the value.
2116 __ mov(FieldOperand(object, offset), value); 2127 __ mov(FieldOperand(object, offset), value);
2117 2128
2118 // Cells are always in the remembered set. 2129 // Cells are always in the remembered set.
2119 __ RecordWriteField(object, 2130 if (instr->hydrogen()->NeedsWriteBarrier()) {
2120 offset, 2131 HType type = instr->hydrogen()->value()->type();
2121 value, 2132 SmiCheck check_needed =
2122 address, 2133 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
2123 kSaveFPRegs, 2134 __ RecordWriteField(object,
2124 OMIT_REMEMBERED_SET); 2135 offset,
2136 value,
2137 address,
2138 kSaveFPRegs,
2139 OMIT_REMEMBERED_SET,
2140 check_needed);
2141 }
2125 } 2142 }
2126 2143
2127 2144
2128 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { 2145 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
2129 ASSERT(ToRegister(instr->context()).is(esi)); 2146 ASSERT(ToRegister(instr->context()).is(esi));
2130 ASSERT(ToRegister(instr->global_object()).is(edx)); 2147 ASSERT(ToRegister(instr->global_object()).is(edx));
2131 ASSERT(ToRegister(instr->value()).is(eax)); 2148 ASSERT(ToRegister(instr->value()).is(eax));
2132 2149
2133 __ mov(ecx, instr->name()); 2150 __ mov(ecx, instr->name());
2134 Handle<Code> ic = instr->strict_mode() 2151 Handle<Code> ic = instr->strict_mode()
2135 ? isolate()->builtins()->StoreIC_Initialize_Strict() 2152 ? isolate()->builtins()->StoreIC_Initialize_Strict()
2136 : isolate()->builtins()->StoreIC_Initialize(); 2153 : isolate()->builtins()->StoreIC_Initialize();
2137 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); 2154 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr);
2138 } 2155 }
2139 2156
2140 2157
2141 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { 2158 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
2142 Register context = ToRegister(instr->context()); 2159 Register context = ToRegister(instr->context());
2143 Register result = ToRegister(instr->result()); 2160 Register result = ToRegister(instr->result());
2144 __ mov(result, ContextOperand(context, instr->slot_index())); 2161 __ mov(result, ContextOperand(context, instr->slot_index()));
2145 } 2162 }
2146 2163
2147 2164
2148 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { 2165 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
2149 Register context = ToRegister(instr->context()); 2166 Register context = ToRegister(instr->context());
2150 Register value = ToRegister(instr->value()); 2167 Register value = ToRegister(instr->value());
2151 __ mov(ContextOperand(context, instr->slot_index()), value); 2168 __ mov(ContextOperand(context, instr->slot_index()), value);
2152 if (instr->needs_write_barrier()) { 2169 if (instr->hydrogen()->NeedsWriteBarrier()) {
2170 HType type = instr->hydrogen()->value()->type();
2171 SmiCheck check_needed =
2172 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
2153 Register temp = ToRegister(instr->TempAt(0)); 2173 Register temp = ToRegister(instr->TempAt(0));
2154 int offset = Context::SlotOffset(instr->slot_index()); 2174 int offset = Context::SlotOffset(instr->slot_index());
2155 __ RecordWriteContextSlot(context, offset, value, temp, kSaveFPRegs); 2175 __ RecordWriteContextSlot(context,
2176 offset,
2177 value,
2178 temp,
2179 kSaveFPRegs,
2180 EMIT_REMEMBERED_SET,
2181 check_needed);
2156 } 2182 }
2157 } 2183 }
2158 2184
2159 2185
2160 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { 2186 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
2161 Register object = ToRegister(instr->object()); 2187 Register object = ToRegister(instr->object());
2162 Register result = ToRegister(instr->result()); 2188 Register result = ToRegister(instr->result());
2163 if (instr->hydrogen()->is_in_object()) { 2189 if (instr->hydrogen()->is_in_object()) {
2164 __ mov(result, FieldOperand(object, instr->hydrogen()->offset())); 2190 __ mov(result, FieldOperand(object, instr->hydrogen()->offset()));
2165 } else { 2191 } else {
2166 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); 2192 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset));
2167 __ mov(result, FieldOperand(result, instr->hydrogen()->offset())); 2193 __ mov(result, FieldOperand(result, instr->hydrogen()->offset()));
2168 } 2194 }
2169 } 2195 }
2170 2196
2171 2197
2172 void LCodeGen::EmitLoadFieldOrConstantFunction(Register result, 2198 void LCodeGen::EmitLoadFieldOrConstantFunction(Register result,
2173 Register object, 2199 Register object,
2174 Handle<Map> type, 2200 Handle<Map> type,
2175 Handle<String> name) { 2201 Handle<String> name) {
2176 LookupResult lookup; 2202 LookupResult lookup(isolate());
2177 type->LookupInDescriptors(NULL, *name, &lookup); 2203 type->LookupInDescriptors(NULL, *name, &lookup);
2178 ASSERT(lookup.IsProperty() && 2204 ASSERT(lookup.IsProperty() &&
2179 (lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION)); 2205 (lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION));
2180 if (lookup.type() == FIELD) { 2206 if (lookup.type() == FIELD) {
2181 int index = lookup.GetLocalFieldIndexFromMap(*type); 2207 int index = lookup.GetLocalFieldIndexFromMap(*type);
2182 int offset = index * kPointerSize; 2208 int offset = index * kPointerSize;
2183 if (index < 0) { 2209 if (index < 0) {
2184 // Negative property indices are in-object properties, indexed 2210 // Negative property indices are in-object properties, indexed
2185 // from the end of the fixed part of the object. 2211 // from the end of the fixed part of the object.
2186 __ mov(result, FieldOperand(object, offset + type->instance_size())); 2212 __ mov(result, FieldOperand(object, offset + type->instance_size()));
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after
2607 if (argument->IsConstantOperand()) { 2633 if (argument->IsConstantOperand()) {
2608 __ push(ToImmediate(argument)); 2634 __ push(ToImmediate(argument));
2609 } else { 2635 } else {
2610 __ push(ToOperand(argument)); 2636 __ push(ToOperand(argument));
2611 } 2637 }
2612 } 2638 }
2613 2639
2614 2640
2615 void LCodeGen::DoThisFunction(LThisFunction* instr) { 2641 void LCodeGen::DoThisFunction(LThisFunction* instr) {
2616 Register result = ToRegister(instr->result()); 2642 Register result = ToRegister(instr->result());
2617 __ mov(result, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 2643 LoadHeapObject(result, instr->hydrogen()->closure());
2618 } 2644 }
2619 2645
2620 2646
2621 void LCodeGen::DoContext(LContext* instr) { 2647 void LCodeGen::DoContext(LContext* instr) {
2622 Register result = ToRegister(instr->result()); 2648 Register result = ToRegister(instr->result());
2623 __ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset)); 2649 __ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset));
2624 } 2650 }
2625 2651
2626 2652
2627 void LCodeGen::DoOuterContext(LOuterContext* instr) { 2653 void LCodeGen::DoOuterContext(LOuterContext* instr) {
(...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after
3139 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { 3165 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
3140 Register object = ToRegister(instr->object()); 3166 Register object = ToRegister(instr->object());
3141 Register value = ToRegister(instr->value()); 3167 Register value = ToRegister(instr->value());
3142 int offset = instr->offset(); 3168 int offset = instr->offset();
3143 3169
3144 if (!instr->transition().is_null()) { 3170 if (!instr->transition().is_null()) {
3145 __ mov(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); 3171 __ mov(FieldOperand(object, HeapObject::kMapOffset), instr->transition());
3146 } 3172 }
3147 3173
3148 // Do the store. 3174 // Do the store.
3175 HType type = instr->hydrogen()->value()->type();
3176 SmiCheck check_needed =
3177 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
3149 if (instr->is_in_object()) { 3178 if (instr->is_in_object()) {
3150 __ mov(FieldOperand(object, offset), value); 3179 __ mov(FieldOperand(object, offset), value);
3151 if (instr->needs_write_barrier()) { 3180 if (instr->hydrogen()->NeedsWriteBarrier()) {
3152 Register temp = ToRegister(instr->TempAt(0)); 3181 Register temp = ToRegister(instr->TempAt(0));
3153 // Update the write barrier for the object for in-object properties. 3182 // Update the write barrier for the object for in-object properties.
3154 __ RecordWriteField(object, offset, value, temp, kSaveFPRegs); 3183 __ RecordWriteField(object,
3184 offset,
3185 value,
3186 temp,
3187 kSaveFPRegs,
3188 EMIT_REMEMBERED_SET,
3189 check_needed);
3155 } 3190 }
3156 } else { 3191 } else {
3157 Register temp = ToRegister(instr->TempAt(0)); 3192 Register temp = ToRegister(instr->TempAt(0));
3158 __ mov(temp, FieldOperand(object, JSObject::kPropertiesOffset)); 3193 __ mov(temp, FieldOperand(object, JSObject::kPropertiesOffset));
3159 __ mov(FieldOperand(temp, offset), value); 3194 __ mov(FieldOperand(temp, offset), value);
3160 if (instr->needs_write_barrier()) { 3195 if (instr->hydrogen()->NeedsWriteBarrier()) {
3161 // Update the write barrier for the properties array. 3196 // Update the write barrier for the properties array.
3162 // object is used as a scratch register. 3197 // object is used as a scratch register.
3163 __ RecordWriteField(temp, offset, value, object, kSaveFPRegs); 3198 __ RecordWriteField(temp,
3199 offset,
3200 value,
3201 object,
3202 kSaveFPRegs,
3203 EMIT_REMEMBERED_SET,
3204 check_needed);
3164 } 3205 }
3165 } 3206 }
3166 } 3207 }
3167 3208
3168 3209
3169 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { 3210 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
3170 ASSERT(ToRegister(instr->context()).is(esi)); 3211 ASSERT(ToRegister(instr->context()).is(esi));
3171 ASSERT(ToRegister(instr->object()).is(edx)); 3212 ASSERT(ToRegister(instr->object()).is(edx));
3172 ASSERT(ToRegister(instr->value()).is(eax)); 3213 ASSERT(ToRegister(instr->value()).is(eax));
3173 3214
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
3252 __ mov(FieldOperand(elements, offset), value); 3293 __ mov(FieldOperand(elements, offset), value);
3253 } else { 3294 } else {
3254 __ mov(FieldOperand(elements, 3295 __ mov(FieldOperand(elements,
3255 key, 3296 key,
3256 times_pointer_size, 3297 times_pointer_size,
3257 FixedArray::kHeaderSize), 3298 FixedArray::kHeaderSize),
3258 value); 3299 value);
3259 } 3300 }
3260 3301
3261 if (instr->hydrogen()->NeedsWriteBarrier()) { 3302 if (instr->hydrogen()->NeedsWriteBarrier()) {
3303 HType type = instr->hydrogen()->value()->type();
3304 SmiCheck check_needed =
3305 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
3262 // Compute address of modified element and store it into key register. 3306 // Compute address of modified element and store it into key register.
3263 __ lea(key, 3307 __ lea(key,
3264 FieldOperand(elements, 3308 FieldOperand(elements,
3265 key, 3309 key,
3266 times_pointer_size, 3310 times_pointer_size,
3267 FixedArray::kHeaderSize)); 3311 FixedArray::kHeaderSize));
3268 __ RecordWrite(elements, key, value, kSaveFPRegs); 3312 __ RecordWrite(elements,
3313 key,
3314 value,
3315 kSaveFPRegs,
3316 EMIT_REMEMBERED_SET,
3317 check_needed);
3269 } 3318 }
3270 } 3319 }
3271 3320
3272 3321
3273 void LCodeGen::DoStoreKeyedFastDoubleElement( 3322 void LCodeGen::DoStoreKeyedFastDoubleElement(
3274 LStoreKeyedFastDoubleElement* instr) { 3323 LStoreKeyedFastDoubleElement* instr) {
3275 XMMRegister value = ToDoubleRegister(instr->value()); 3324 XMMRegister value = ToDoubleRegister(instr->value());
3276 Label have_value; 3325 Label have_value;
3277 3326
3278 __ ucomisd(value, value); 3327 __ ucomisd(value, value);
(...skipping 17 matching lines...) Expand all
3296 ASSERT(ToRegister(instr->key()).is(ecx)); 3345 ASSERT(ToRegister(instr->key()).is(ecx));
3297 ASSERT(ToRegister(instr->value()).is(eax)); 3346 ASSERT(ToRegister(instr->value()).is(eax));
3298 3347
3299 Handle<Code> ic = instr->strict_mode() 3348 Handle<Code> ic = instr->strict_mode()
3300 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() 3349 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
3301 : isolate()->builtins()->KeyedStoreIC_Initialize(); 3350 : isolate()->builtins()->KeyedStoreIC_Initialize();
3302 CallCode(ic, RelocInfo::CODE_TARGET, instr); 3351 CallCode(ic, RelocInfo::CODE_TARGET, instr);
3303 } 3352 }
3304 3353
3305 3354
3355 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
3356 Register object_reg = ToRegister(instr->object());
3357 Register new_map_reg = ToRegister(instr->new_map_reg());
3358
3359 Handle<Map> from_map = instr->original_map();
3360 Handle<Map> to_map = instr->transitioned_map();
3361 ElementsKind from_kind = from_map->elements_kind();
3362 ElementsKind to_kind = to_map->elements_kind();
3363
3364 Label not_applicable;
3365 __ cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map);
3366 __ j(not_equal, &not_applicable);
3367 __ mov(new_map_reg, to_map);
3368 if (from_kind == FAST_SMI_ONLY_ELEMENTS && to_kind == FAST_ELEMENTS) {
3369 Register object_reg = ToRegister(instr->object());
3370 __ mov(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg);
3371 // Write barrier.
3372 ASSERT_NE(instr->temp_reg(), NULL);
3373 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg,
3374 ToRegister(instr->temp_reg()), kDontSaveFPRegs);
3375 } else if (from_kind == FAST_SMI_ONLY_ELEMENTS &&
3376 to_kind == FAST_DOUBLE_ELEMENTS) {
3377 Register fixed_object_reg = ToRegister(instr->temp_reg());
3378 ASSERT(fixed_object_reg.is(edx));
3379 ASSERT(new_map_reg.is(ebx));
3380 __ mov(fixed_object_reg, object_reg);
3381 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(),
3382 RelocInfo::CODE_TARGET, instr);
3383 } else if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) {
3384 Register fixed_object_reg = ToRegister(instr->temp_reg());
3385 ASSERT(fixed_object_reg.is(edx));
3386 ASSERT(new_map_reg.is(ebx));
3387 __ mov(fixed_object_reg, object_reg);
3388 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(),
3389 RelocInfo::CODE_TARGET, instr);
3390 } else {
3391 UNREACHABLE();
3392 }
3393 __ bind(&not_applicable);
3394 }
3395
3396
3306 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { 3397 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
3307 class DeferredStringCharCodeAt: public LDeferredCode { 3398 class DeferredStringCharCodeAt: public LDeferredCode {
3308 public: 3399 public:
3309 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) 3400 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr)
3310 : LDeferredCode(codegen), instr_(instr) { } 3401 : LDeferredCode(codegen), instr_(instr) { }
3311 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); } 3402 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); }
3312 virtual LInstruction* instr() { return instr_; } 3403 virtual LInstruction* instr() { return instr_; }
3313 private: 3404 private:
3314 LStringCharCodeAt* instr_; 3405 LStringCharCodeAt* instr_;
3315 }; 3406 };
(...skipping 772 matching lines...) Expand 10 before | Expand all | Expand 10 after
4088 4179
4089 // Check the holder map. 4180 // Check the holder map.
4090 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), 4181 __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
4091 Handle<Map>(current_prototype->map())); 4182 Handle<Map>(current_prototype->map()));
4092 DeoptimizeIf(not_equal, instr->environment()); 4183 DeoptimizeIf(not_equal, instr->environment());
4093 } 4184 }
4094 4185
4095 4186
4096 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { 4187 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
4097 ASSERT(ToRegister(instr->context()).is(esi)); 4188 ASSERT(ToRegister(instr->context()).is(esi));
4189
4190 Handle<FixedArray> constant_elements = instr->hydrogen()->constant_elements();
4191 ASSERT_EQ(2, constant_elements->length());
4192 ElementsKind constant_elements_kind =
4193 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
4194
4098 // Setup the parameters to the stub/runtime call. 4195 // Setup the parameters to the stub/runtime call.
4099 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 4196 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
4100 __ push(FieldOperand(eax, JSFunction::kLiteralsOffset)); 4197 __ push(FieldOperand(eax, JSFunction::kLiteralsOffset));
4101 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); 4198 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index())));
4102 __ push(Immediate(instr->hydrogen()->constant_elements())); 4199 __ push(Immediate(constant_elements));
4103 4200
4104 // Pick the right runtime function or stub to call. 4201 // Pick the right runtime function or stub to call.
4105 int length = instr->hydrogen()->length(); 4202 int length = instr->hydrogen()->length();
4106 if (instr->hydrogen()->IsCopyOnWrite()) { 4203 if (instr->hydrogen()->IsCopyOnWrite()) {
4107 ASSERT(instr->hydrogen()->depth() == 1); 4204 ASSERT(instr->hydrogen()->depth() == 1);
4108 FastCloneShallowArrayStub::Mode mode = 4205 FastCloneShallowArrayStub::Mode mode =
4109 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS; 4206 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS;
4110 FastCloneShallowArrayStub stub(mode, length); 4207 FastCloneShallowArrayStub stub(mode, length);
4111 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 4208 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4112 } else if (instr->hydrogen()->depth() > 1) { 4209 } else if (instr->hydrogen()->depth() > 1) {
4113 CallRuntime(Runtime::kCreateArrayLiteral, 3, instr); 4210 CallRuntime(Runtime::kCreateArrayLiteral, 3, instr);
4114 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { 4211 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
4115 CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr); 4212 CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr);
4116 } else { 4213 } else {
4117 FastCloneShallowArrayStub::Mode mode = 4214 FastCloneShallowArrayStub::Mode mode =
4118 FastCloneShallowArrayStub::CLONE_ELEMENTS; 4215 constant_elements_kind == FAST_DOUBLE_ELEMENTS
4216 ? FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS
4217 : FastCloneShallowArrayStub::CLONE_ELEMENTS;
4119 FastCloneShallowArrayStub stub(mode, length); 4218 FastCloneShallowArrayStub stub(mode, length);
4120 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 4219 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4121 } 4220 }
4122 } 4221 }
4123 4222
4124 4223
4125 void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) { 4224 void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) {
4126 ASSERT(ToRegister(instr->context()).is(esi)); 4225 ASSERT(ToRegister(instr->context()).is(esi));
4127 // Setup the parameters to the stub/runtime call. 4226 // Setup the parameters to the stub/runtime call.
4128 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 4227 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
4207 } 4306 }
4208 4307
4209 4308
4210 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { 4309 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
4211 ASSERT(ToRegister(instr->context()).is(esi)); 4310 ASSERT(ToRegister(instr->context()).is(esi));
4212 // Use the fast case closure allocation code that allocates in new 4311 // Use the fast case closure allocation code that allocates in new
4213 // space for nested functions that don't need literals cloning. 4312 // space for nested functions that don't need literals cloning.
4214 Handle<SharedFunctionInfo> shared_info = instr->shared_info(); 4313 Handle<SharedFunctionInfo> shared_info = instr->shared_info();
4215 bool pretenure = instr->hydrogen()->pretenure(); 4314 bool pretenure = instr->hydrogen()->pretenure();
4216 if (!pretenure && shared_info->num_literals() == 0) { 4315 if (!pretenure && shared_info->num_literals() == 0) {
4217 FastNewClosureStub stub( 4316 FastNewClosureStub stub(shared_info->strict_mode_flag());
4218 shared_info->strict_mode() ? kStrictMode : kNonStrictMode);
4219 __ push(Immediate(shared_info)); 4317 __ push(Immediate(shared_info));
4220 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 4318 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4221 } else { 4319 } else {
4222 __ push(Operand(ebp, StandardFrameConstants::kContextOffset)); 4320 __ push(Operand(ebp, StandardFrameConstants::kContextOffset));
4223 __ push(Immediate(shared_info)); 4321 __ push(Immediate(shared_info));
4224 __ push(Immediate(pretenure 4322 __ push(Immediate(pretenure
4225 ? factory()->true_value() 4323 ? factory()->true_value()
4226 : factory()->false_value())); 4324 : factory()->false_value()));
4227 CallRuntime(Runtime::kNewClosure, 3, instr); 4325 CallRuntime(Runtime::kNewClosure, 3, instr);
4228 } 4326 }
(...skipping 11 matching lines...) Expand all
4240 } 4338 }
4241 4339
4242 4340
4243 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { 4341 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
4244 Register input = ToRegister(instr->InputAt(0)); 4342 Register input = ToRegister(instr->InputAt(0));
4245 int true_block = chunk_->LookupDestination(instr->true_block_id()); 4343 int true_block = chunk_->LookupDestination(instr->true_block_id());
4246 int false_block = chunk_->LookupDestination(instr->false_block_id()); 4344 int false_block = chunk_->LookupDestination(instr->false_block_id());
4247 Label* true_label = chunk_->GetAssemblyLabel(true_block); 4345 Label* true_label = chunk_->GetAssemblyLabel(true_block);
4248 Label* false_label = chunk_->GetAssemblyLabel(false_block); 4346 Label* false_label = chunk_->GetAssemblyLabel(false_block);
4249 4347
4250 Condition final_branch_condition = EmitTypeofIs(true_label, 4348 Condition final_branch_condition =
4251 false_label, 4349 EmitTypeofIs(true_label, false_label, input, instr->type_literal());
4252 input, 4350 if (final_branch_condition != no_condition) {
4253 instr->type_literal()); 4351 EmitBranch(true_block, false_block, final_branch_condition);
4254 4352 }
4255 EmitBranch(true_block, false_block, final_branch_condition);
4256 } 4353 }
4257 4354
4258 4355
4259 Condition LCodeGen::EmitTypeofIs(Label* true_label, 4356 Condition LCodeGen::EmitTypeofIs(Label* true_label,
4260 Label* false_label, 4357 Label* false_label,
4261 Register input, 4358 Register input,
4262 Handle<String> type_name) { 4359 Handle<String> type_name) {
4263 Condition final_branch_condition = no_condition; 4360 Condition final_branch_condition = no_condition;
4264 if (type_name->Equals(heap()->number_symbol())) { 4361 if (type_name->Equals(heap()->number_symbol())) {
4265 __ JumpIfSmi(input, true_label); 4362 __ JumpIfSmi(input, true_label);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
4312 __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input); 4409 __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input);
4313 __ j(below, false_label); 4410 __ j(below, false_label);
4314 __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); 4411 __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
4315 __ j(above, false_label); 4412 __ j(above, false_label);
4316 // Check for undetectable objects => false. 4413 // Check for undetectable objects => false.
4317 __ test_b(FieldOperand(input, Map::kBitFieldOffset), 4414 __ test_b(FieldOperand(input, Map::kBitFieldOffset),
4318 1 << Map::kIsUndetectable); 4415 1 << Map::kIsUndetectable);
4319 final_branch_condition = zero; 4416 final_branch_condition = zero;
4320 4417
4321 } else { 4418 } else {
4322 final_branch_condition = not_equal;
4323 __ jmp(false_label); 4419 __ jmp(false_label);
4324 // A dead branch instruction will be generated after this point.
4325 } 4420 }
4326
4327 return final_branch_condition; 4421 return final_branch_condition;
4328 } 4422 }
4329 4423
4330 4424
4331 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { 4425 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
4332 Register temp = ToRegister(instr->TempAt(0)); 4426 Register temp = ToRegister(instr->TempAt(0));
4333 int true_block = chunk_->LookupDestination(instr->true_block_id()); 4427 int true_block = chunk_->LookupDestination(instr->true_block_id());
4334 int false_block = chunk_->LookupDestination(instr->false_block_id()); 4428 int false_block = chunk_->LookupDestination(instr->false_block_id());
4335 4429
4336 EmitIsConstructCall(temp); 4430 EmitIsConstructCall(temp);
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
4489 env->deoptimization_index()); 4583 env->deoptimization_index());
4490 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); 4584 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator);
4491 } 4585 }
4492 4586
4493 4587
4494 #undef __ 4588 #undef __
4495 4589
4496 } } // namespace v8::internal 4590 } } // namespace v8::internal
4497 4591
4498 #endif // V8_TARGET_ARCH_IA32 4592 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698