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

Side by Side Diff: src/x64/lithium-codegen-x64.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/x64/lithium-codegen-x64.h ('k') | src/x64/lithium-x64.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 356 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 367
368 int LCodeGen::ToInteger32(LConstantOperand* op) const { 368 int LCodeGen::ToInteger32(LConstantOperand* op) const {
369 Handle<Object> value = chunk_->LookupLiteral(op); 369 Handle<Object> value = chunk_->LookupLiteral(op);
370 ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32()); 370 ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32());
371 ASSERT(static_cast<double>(static_cast<int32_t>(value->Number())) == 371 ASSERT(static_cast<double>(static_cast<int32_t>(value->Number())) ==
372 value->Number()); 372 value->Number());
373 return static_cast<int32_t>(value->Number()); 373 return static_cast<int32_t>(value->Number());
374 } 374 }
375 375
376 376
377 double LCodeGen::ToDouble(LConstantOperand* op) const {
378 Handle<Object> value = chunk_->LookupLiteral(op);
379 return value->Number();
380 }
381
382
377 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const { 383 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
378 Handle<Object> literal = chunk_->LookupLiteral(op); 384 Handle<Object> literal = chunk_->LookupLiteral(op);
379 ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged()); 385 ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged());
380 return literal; 386 return literal;
381 } 387 }
382 388
383 389
384 Operand LCodeGen::ToOperand(LOperand* op) const { 390 Operand LCodeGen::ToOperand(LOperand* op) const {
385 // Does not handle registers. In X64 assembler, plain registers are not 391 // Does not handle registers. In X64 assembler, plain registers are not
386 // representable as an Operand. 392 // representable as an Operand.
(...skipping 1132 matching lines...) Expand 10 before | Expand all | Expand 10 after
1519 break; 1525 break;
1520 case Token::IN: 1526 case Token::IN:
1521 case Token::INSTANCEOF: 1527 case Token::INSTANCEOF:
1522 default: 1528 default:
1523 UNREACHABLE(); 1529 UNREACHABLE();
1524 } 1530 }
1525 return cond; 1531 return cond;
1526 } 1532 }
1527 1533
1528 1534
1529 void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) {
1530 if (right->IsConstantOperand()) {
1531 int32_t value = ToInteger32(LConstantOperand::cast(right));
1532 if (left->IsRegister()) {
1533 __ cmpl(ToRegister(left), Immediate(value));
1534 } else {
1535 __ cmpl(ToOperand(left), Immediate(value));
1536 }
1537 } else if (right->IsRegister()) {
1538 __ cmpl(ToRegister(left), ToRegister(right));
1539 } else {
1540 __ cmpl(ToRegister(left), ToOperand(right));
1541 }
1542 }
1543
1544
1545 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { 1535 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
1546 LOperand* left = instr->InputAt(0); 1536 LOperand* left = instr->InputAt(0);
1547 LOperand* right = instr->InputAt(1); 1537 LOperand* right = instr->InputAt(1);
1548 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1538 int false_block = chunk_->LookupDestination(instr->false_block_id());
1549 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1539 int true_block = chunk_->LookupDestination(instr->true_block_id());
1540 Condition cc = TokenToCondition(instr->op(), instr->is_double());
1550 1541
1551 if (instr->is_double()) { 1542 if (left->IsConstantOperand() && right->IsConstantOperand()) {
1552 // Don't base result on EFLAGS when a NaN is involved. Instead 1543 // We can statically evaluate the comparison.
1553 // jump to the false block. 1544 double left_val = ToDouble(LConstantOperand::cast(left));
1554 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); 1545 double right_val = ToDouble(LConstantOperand::cast(right));
1555 __ j(parity_even, chunk_->GetAssemblyLabel(false_block)); 1546 int next_block =
1547 EvalComparison(instr->op(), left_val, right_val) ? true_block
1548 : false_block;
1549 EmitGoto(next_block);
1556 } else { 1550 } else {
1557 EmitCmpI(left, right); 1551 if (instr->is_double()) {
1552 // Don't base result on EFLAGS when a NaN is involved. Instead
1553 // jump to the false block.
1554 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
1555 __ j(parity_even, chunk_->GetAssemblyLabel(false_block));
1556 } else {
1557 int32_t value;
1558 if (right->IsConstantOperand()) {
1559 value = ToInteger32(LConstantOperand::cast(right));
1560 __ cmpl(ToRegister(left), Immediate(value));
1561 } else if (left->IsConstantOperand()) {
1562 value = ToInteger32(LConstantOperand::cast(left));
1563 if (right->IsRegister()) {
1564 __ cmpl(ToRegister(right), Immediate(value));
1565 } else {
1566 __ cmpl(ToOperand(right), Immediate(value));
1567 }
1568 // We transposed the operands. Reverse the condition.
1569 cc = ReverseCondition(cc);
1570 } else {
1571 if (right->IsRegister()) {
1572 __ cmpl(ToRegister(left), ToRegister(right));
1573 } else {
1574 __ cmpl(ToRegister(left), ToOperand(right));
1575 }
1576 }
1577 }
1578 EmitBranch(true_block, false_block, cc);
1558 } 1579 }
1559
1560 Condition cc = TokenToCondition(instr->op(), instr->is_double());
1561 EmitBranch(true_block, false_block, cc);
1562 } 1580 }
1563 1581
1564 1582
1565 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { 1583 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
1566 Register left = ToRegister(instr->InputAt(0)); 1584 Register left = ToRegister(instr->InputAt(0));
1567 Register right = ToRegister(instr->InputAt(1)); 1585 Register right = ToRegister(instr->InputAt(1));
1568 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1586 int false_block = chunk_->LookupDestination(instr->false_block_id());
1569 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1587 int true_block = chunk_->LookupDestination(instr->true_block_id());
1570 1588
1571 __ cmpq(left, right); 1589 __ cmpq(left, right);
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after
1972 } 1990 }
1973 1991
1974 1992
1975 void LCodeGen::DoCmpT(LCmpT* instr) { 1993 void LCodeGen::DoCmpT(LCmpT* instr) {
1976 Token::Value op = instr->op(); 1994 Token::Value op = instr->op();
1977 1995
1978 Handle<Code> ic = CompareIC::GetUninitialized(op); 1996 Handle<Code> ic = CompareIC::GetUninitialized(op);
1979 CallCode(ic, RelocInfo::CODE_TARGET, instr); 1997 CallCode(ic, RelocInfo::CODE_TARGET, instr);
1980 1998
1981 Condition condition = TokenToCondition(op, false); 1999 Condition condition = TokenToCondition(op, false);
1982 if (op == Token::GT || op == Token::LTE) {
1983 condition = ReverseCondition(condition);
1984 }
1985 Label true_value, done; 2000 Label true_value, done;
1986 __ testq(rax, rax); 2001 __ testq(rax, rax);
1987 __ j(condition, &true_value, Label::kNear); 2002 __ j(condition, &true_value, Label::kNear);
1988 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); 2003 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex);
1989 __ jmp(&done, Label::kNear); 2004 __ jmp(&done, Label::kNear);
1990 __ bind(&true_value); 2005 __ bind(&true_value);
1991 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); 2006 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex);
1992 __ bind(&done); 2007 __ bind(&done);
1993 } 2008 }
1994 2009
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
2048 // to update the property details in the property dictionary to mark 2063 // to update the property details in the property dictionary to mark
2049 // it as no longer deleted. We deoptimize in that case. 2064 // it as no longer deleted. We deoptimize in that case.
2050 if (instr->hydrogen()->RequiresHoleCheck()) { 2065 if (instr->hydrogen()->RequiresHoleCheck()) {
2051 __ CompareRoot(Operand(address, 0), Heap::kTheHoleValueRootIndex); 2066 __ CompareRoot(Operand(address, 0), Heap::kTheHoleValueRootIndex);
2052 DeoptimizeIf(equal, instr->environment()); 2067 DeoptimizeIf(equal, instr->environment());
2053 } 2068 }
2054 2069
2055 // Store the value. 2070 // Store the value.
2056 __ movq(Operand(address, 0), value); 2071 __ movq(Operand(address, 0), value);
2057 2072
2058 Label smi_store; 2073 if (instr->hydrogen()->NeedsWriteBarrier()) {
2059 __ JumpIfSmi(value, &smi_store, Label::kNear); 2074 Label smi_store;
2075 HType type = instr->hydrogen()->value()->type();
2076 if (!type.IsHeapNumber() && !type.IsString() && !type.IsNonPrimitive()) {
2077 __ JumpIfSmi(value, &smi_store, Label::kNear);
2078 }
2060 2079
2061 int offset = JSGlobalPropertyCell::kValueOffset - kHeapObjectTag; 2080 int offset = JSGlobalPropertyCell::kValueOffset - kHeapObjectTag;
2062 __ lea(object, Operand(address, -offset)); 2081 __ lea(object, Operand(address, -offset));
2063 // Cells are always in the remembered set. 2082 // Cells are always in the remembered set.
2064 __ RecordWrite(object, 2083 __ RecordWrite(object,
2065 address, 2084 address,
2066 value, 2085 value,
2067 kSaveFPRegs, 2086 kSaveFPRegs,
2068 OMIT_REMEMBERED_SET, 2087 OMIT_REMEMBERED_SET,
2069 OMIT_SMI_CHECK); 2088 OMIT_SMI_CHECK);
2070 __ bind(&smi_store); 2089 __ bind(&smi_store);
2090 }
2071 } 2091 }
2072 2092
2073 2093
2074 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { 2094 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
2075 ASSERT(ToRegister(instr->global_object()).is(rdx)); 2095 ASSERT(ToRegister(instr->global_object()).is(rdx));
2076 ASSERT(ToRegister(instr->value()).is(rax)); 2096 ASSERT(ToRegister(instr->value()).is(rax));
2077 2097
2078 __ Move(rcx, instr->name()); 2098 __ Move(rcx, instr->name());
2079 Handle<Code> ic = instr->strict_mode() 2099 Handle<Code> ic = instr->strict_mode()
2080 ? isolate()->builtins()->StoreIC_Initialize_Strict() 2100 ? isolate()->builtins()->StoreIC_Initialize_Strict()
2081 : isolate()->builtins()->StoreIC_Initialize(); 2101 : isolate()->builtins()->StoreIC_Initialize();
2082 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); 2102 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr);
2083 } 2103 }
2084 2104
2085 2105
2086 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { 2106 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
2087 Register context = ToRegister(instr->context()); 2107 Register context = ToRegister(instr->context());
2088 Register result = ToRegister(instr->result()); 2108 Register result = ToRegister(instr->result());
2089 __ movq(result, ContextOperand(context, instr->slot_index())); 2109 __ movq(result, ContextOperand(context, instr->slot_index()));
2090 } 2110 }
2091 2111
2092 2112
2093 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { 2113 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
2094 Register context = ToRegister(instr->context()); 2114 Register context = ToRegister(instr->context());
2095 Register value = ToRegister(instr->value()); 2115 Register value = ToRegister(instr->value());
2096 __ movq(ContextOperand(context, instr->slot_index()), value); 2116 __ movq(ContextOperand(context, instr->slot_index()), value);
2097 if (instr->needs_write_barrier()) { 2117 if (instr->hydrogen()->NeedsWriteBarrier()) {
2118 HType type = instr->hydrogen()->value()->type();
2119 SmiCheck check_needed =
2120 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
2098 int offset = Context::SlotOffset(instr->slot_index()); 2121 int offset = Context::SlotOffset(instr->slot_index());
2099 Register scratch = ToRegister(instr->TempAt(0)); 2122 Register scratch = ToRegister(instr->TempAt(0));
2100 __ RecordWriteContextSlot(context, offset, value, scratch, kSaveFPRegs); 2123 __ RecordWriteContextSlot(context,
2124 offset,
2125 value,
2126 scratch,
2127 kSaveFPRegs,
2128 EMIT_REMEMBERED_SET,
2129 check_needed);
2101 } 2130 }
2102 } 2131 }
2103 2132
2104 2133
2105 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { 2134 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
2106 Register object = ToRegister(instr->InputAt(0)); 2135 Register object = ToRegister(instr->InputAt(0));
2107 Register result = ToRegister(instr->result()); 2136 Register result = ToRegister(instr->result());
2108 if (instr->hydrogen()->is_in_object()) { 2137 if (instr->hydrogen()->is_in_object()) {
2109 __ movq(result, FieldOperand(object, instr->hydrogen()->offset())); 2138 __ movq(result, FieldOperand(object, instr->hydrogen()->offset()));
2110 } else { 2139 } else {
2111 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); 2140 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset));
2112 __ movq(result, FieldOperand(result, instr->hydrogen()->offset())); 2141 __ movq(result, FieldOperand(result, instr->hydrogen()->offset()));
2113 } 2142 }
2114 } 2143 }
2115 2144
2116 2145
2117 void LCodeGen::EmitLoadFieldOrConstantFunction(Register result, 2146 void LCodeGen::EmitLoadFieldOrConstantFunction(Register result,
2118 Register object, 2147 Register object,
2119 Handle<Map> type, 2148 Handle<Map> type,
2120 Handle<String> name) { 2149 Handle<String> name) {
2121 LookupResult lookup; 2150 LookupResult lookup(isolate());
2122 type->LookupInDescriptors(NULL, *name, &lookup); 2151 type->LookupInDescriptors(NULL, *name, &lookup);
2123 ASSERT(lookup.IsProperty() && 2152 ASSERT(lookup.IsProperty() &&
2124 (lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION)); 2153 (lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION));
2125 if (lookup.type() == FIELD) { 2154 if (lookup.type() == FIELD) {
2126 int index = lookup.GetLocalFieldIndexFromMap(*type); 2155 int index = lookup.GetLocalFieldIndexFromMap(*type);
2127 int offset = index * kPointerSize; 2156 int offset = index * kPointerSize;
2128 if (index < 0) { 2157 if (index < 0) {
2129 // Negative property indices are in-object properties, indexed 2158 // Negative property indices are in-object properties, indexed
2130 // from the end of the fixed part of the object. 2159 // from the end of the fixed part of the object.
2131 __ movq(result, FieldOperand(object, offset + type->instance_size())); 2160 __ movq(result, FieldOperand(object, offset + type->instance_size()));
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after
2554 2583
2555 2584
2556 void LCodeGen::DoPushArgument(LPushArgument* instr) { 2585 void LCodeGen::DoPushArgument(LPushArgument* instr) {
2557 LOperand* argument = instr->InputAt(0); 2586 LOperand* argument = instr->InputAt(0);
2558 EmitPushTaggedOperand(argument); 2587 EmitPushTaggedOperand(argument);
2559 } 2588 }
2560 2589
2561 2590
2562 void LCodeGen::DoThisFunction(LThisFunction* instr) { 2591 void LCodeGen::DoThisFunction(LThisFunction* instr) {
2563 Register result = ToRegister(instr->result()); 2592 Register result = ToRegister(instr->result());
2564 __ movq(result, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 2593 LoadHeapObject(result, instr->hydrogen()->closure());
2565 } 2594 }
2566 2595
2567 2596
2568 void LCodeGen::DoContext(LContext* instr) { 2597 void LCodeGen::DoContext(LContext* instr) {
2569 Register result = ToRegister(instr->result()); 2598 Register result = ToRegister(instr->result());
2570 __ movq(result, rsi); 2599 __ movq(result, rsi);
2571 } 2600 }
2572 2601
2573 2602
2574 void LCodeGen::DoOuterContext(LOuterContext* instr) { 2603 void LCodeGen::DoOuterContext(LOuterContext* instr) {
(...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after
3054 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { 3083 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
3055 Register object = ToRegister(instr->object()); 3084 Register object = ToRegister(instr->object());
3056 Register value = ToRegister(instr->value()); 3085 Register value = ToRegister(instr->value());
3057 int offset = instr->offset(); 3086 int offset = instr->offset();
3058 3087
3059 if (!instr->transition().is_null()) { 3088 if (!instr->transition().is_null()) {
3060 __ Move(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); 3089 __ Move(FieldOperand(object, HeapObject::kMapOffset), instr->transition());
3061 } 3090 }
3062 3091
3063 // Do the store. 3092 // Do the store.
3093 HType type = instr->hydrogen()->value()->type();
3094 SmiCheck check_needed =
3095 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
3064 if (instr->is_in_object()) { 3096 if (instr->is_in_object()) {
3065 __ movq(FieldOperand(object, offset), value); 3097 __ movq(FieldOperand(object, offset), value);
3066 if (instr->needs_write_barrier()) { 3098 if (instr->hydrogen()->NeedsWriteBarrier()) {
3067 Register temp = ToRegister(instr->TempAt(0)); 3099 Register temp = ToRegister(instr->TempAt(0));
3068 // Update the write barrier for the object for in-object properties. 3100 // Update the write barrier for the object for in-object properties.
3069 __ RecordWriteField(object, offset, value, temp, kSaveFPRegs); 3101 __ RecordWriteField(object,
3102 offset,
3103 value,
3104 temp,
3105 kSaveFPRegs,
3106 EMIT_REMEMBERED_SET,
3107 check_needed);
3070 } 3108 }
3071 } else { 3109 } else {
3072 Register temp = ToRegister(instr->TempAt(0)); 3110 Register temp = ToRegister(instr->TempAt(0));
3073 __ movq(temp, FieldOperand(object, JSObject::kPropertiesOffset)); 3111 __ movq(temp, FieldOperand(object, JSObject::kPropertiesOffset));
3074 __ movq(FieldOperand(temp, offset), value); 3112 __ movq(FieldOperand(temp, offset), value);
3075 if (instr->needs_write_barrier()) { 3113 if (instr->hydrogen()->NeedsWriteBarrier()) {
3076 // Update the write barrier for the properties array. 3114 // Update the write barrier for the properties array.
3077 // object is used as a scratch register. 3115 // object is used as a scratch register.
3078 __ RecordWriteField(temp, offset, value, object, kSaveFPRegs); 3116 __ RecordWriteField(temp,
3117 offset,
3118 value,
3119 object,
3120 kSaveFPRegs,
3121 EMIT_REMEMBERED_SET,
3122 check_needed);
3079 } 3123 }
3080 } 3124 }
3081 } 3125 }
3082 3126
3083 3127
3084 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { 3128 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
3085 ASSERT(ToRegister(instr->object()).is(rdx)); 3129 ASSERT(ToRegister(instr->object()).is(rdx));
3086 ASSERT(ToRegister(instr->value()).is(rax)); 3130 ASSERT(ToRegister(instr->value()).is(rax));
3087 3131
3088 __ Move(rcx, instr->hydrogen()->name()); 3132 __ Move(rcx, instr->hydrogen()->name());
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
3175 __ movq(FieldOperand(elements, offset), value); 3219 __ movq(FieldOperand(elements, offset), value);
3176 } else { 3220 } else {
3177 __ movq(FieldOperand(elements, 3221 __ movq(FieldOperand(elements,
3178 key, 3222 key,
3179 times_pointer_size, 3223 times_pointer_size,
3180 FixedArray::kHeaderSize), 3224 FixedArray::kHeaderSize),
3181 value); 3225 value);
3182 } 3226 }
3183 3227
3184 if (instr->hydrogen()->NeedsWriteBarrier()) { 3228 if (instr->hydrogen()->NeedsWriteBarrier()) {
3229 HType type = instr->hydrogen()->value()->type();
3230 SmiCheck check_needed =
3231 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
3185 // Compute address of modified element and store it into key register. 3232 // Compute address of modified element and store it into key register.
3186 __ lea(key, FieldOperand(elements, 3233 __ lea(key, FieldOperand(elements,
3187 key, 3234 key,
3188 times_pointer_size, 3235 times_pointer_size,
3189 FixedArray::kHeaderSize)); 3236 FixedArray::kHeaderSize));
3190 __ RecordWrite(elements, key, value, kSaveFPRegs); 3237 __ RecordWrite(elements,
3238 key,
3239 value,
3240 kSaveFPRegs,
3241 EMIT_REMEMBERED_SET,
3242 check_needed);
3191 } 3243 }
3192 } 3244 }
3193 3245
3194 3246
3195 void LCodeGen::DoStoreKeyedFastDoubleElement( 3247 void LCodeGen::DoStoreKeyedFastDoubleElement(
3196 LStoreKeyedFastDoubleElement* instr) { 3248 LStoreKeyedFastDoubleElement* instr) {
3197 XMMRegister value = ToDoubleRegister(instr->value()); 3249 XMMRegister value = ToDoubleRegister(instr->value());
3198 Label have_value; 3250 Label have_value;
3199 3251
3200 __ ucomisd(value, value); 3252 __ ucomisd(value, value);
(...skipping 15 matching lines...) Expand all
3216 ASSERT(ToRegister(instr->key()).is(rcx)); 3268 ASSERT(ToRegister(instr->key()).is(rcx));
3217 ASSERT(ToRegister(instr->value()).is(rax)); 3269 ASSERT(ToRegister(instr->value()).is(rax));
3218 3270
3219 Handle<Code> ic = instr->strict_mode() 3271 Handle<Code> ic = instr->strict_mode()
3220 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() 3272 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
3221 : isolate()->builtins()->KeyedStoreIC_Initialize(); 3273 : isolate()->builtins()->KeyedStoreIC_Initialize();
3222 CallCode(ic, RelocInfo::CODE_TARGET, instr); 3274 CallCode(ic, RelocInfo::CODE_TARGET, instr);
3223 } 3275 }
3224 3276
3225 3277
3278 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
3279 Register object_reg = ToRegister(instr->object());
3280 Register new_map_reg = ToRegister(instr->new_map_reg());
3281
3282 Handle<Map> from_map = instr->original_map();
3283 Handle<Map> to_map = instr->transitioned_map();
3284 ElementsKind from_kind = from_map->elements_kind();
3285 ElementsKind to_kind = to_map->elements_kind();
3286
3287 Label not_applicable;
3288 __ Cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map);
3289 __ j(not_equal, &not_applicable);
3290 __ movq(new_map_reg, to_map, RelocInfo::EMBEDDED_OBJECT);
3291 if (from_kind == FAST_SMI_ONLY_ELEMENTS && to_kind == FAST_ELEMENTS) {
3292 __ movq(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg);
3293 // Write barrier.
3294 ASSERT_NE(instr->temp_reg(), NULL);
3295 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg,
3296 ToRegister(instr->temp_reg()), kDontSaveFPRegs);
3297 } else if (from_kind == FAST_SMI_ONLY_ELEMENTS &&
3298 to_kind == FAST_DOUBLE_ELEMENTS) {
3299 Register fixed_object_reg = ToRegister(instr->temp_reg());
3300 ASSERT(fixed_object_reg.is(rdx));
3301 ASSERT(new_map_reg.is(rbx));
3302 __ movq(fixed_object_reg, object_reg);
3303 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(),
3304 RelocInfo::CODE_TARGET, instr);
3305 } else if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) {
3306 Register fixed_object_reg = ToRegister(instr->temp_reg());
3307 ASSERT(fixed_object_reg.is(rdx));
3308 ASSERT(new_map_reg.is(rbx));
3309 __ movq(fixed_object_reg, object_reg);
3310 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(),
3311 RelocInfo::CODE_TARGET, instr);
3312 } else {
3313 UNREACHABLE();
3314 }
3315 __ bind(&not_applicable);
3316 }
3317
3318
3226 void LCodeGen::DoStringAdd(LStringAdd* instr) { 3319 void LCodeGen::DoStringAdd(LStringAdd* instr) {
3227 EmitPushTaggedOperand(instr->left()); 3320 EmitPushTaggedOperand(instr->left());
3228 EmitPushTaggedOperand(instr->right()); 3321 EmitPushTaggedOperand(instr->right());
3229 StringAddStub stub(NO_STRING_CHECK_IN_STUB); 3322 StringAddStub stub(NO_STRING_CHECK_IN_STUB);
3230 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 3323 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
3231 } 3324 }
3232 3325
3233 3326
3234 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { 3327 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
3235 class DeferredStringCharCodeAt: public LDeferredCode { 3328 class DeferredStringCharCodeAt: public LDeferredCode {
(...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after
3818 } 3911 }
3819 3912
3820 // Check the holder map. 3913 // Check the holder map.
3821 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), 3914 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset),
3822 Handle<Map>(current_prototype->map())); 3915 Handle<Map>(current_prototype->map()));
3823 DeoptimizeIf(not_equal, instr->environment()); 3916 DeoptimizeIf(not_equal, instr->environment());
3824 } 3917 }
3825 3918
3826 3919
3827 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { 3920 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
3921 Handle<FixedArray> constant_elements = instr->hydrogen()->constant_elements();
3922 ASSERT_EQ(2, constant_elements->length());
3923 ElementsKind constant_elements_kind =
3924 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
3925
3828 // Setup the parameters to the stub/runtime call. 3926 // Setup the parameters to the stub/runtime call.
3829 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 3927 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
3830 __ push(FieldOperand(rax, JSFunction::kLiteralsOffset)); 3928 __ push(FieldOperand(rax, JSFunction::kLiteralsOffset));
3831 __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); 3929 __ Push(Smi::FromInt(instr->hydrogen()->literal_index()));
3832 __ Push(instr->hydrogen()->constant_elements()); 3930 __ Push(instr->hydrogen()->constant_elements());
3833 3931
3834 // Pick the right runtime function or stub to call. 3932 // Pick the right runtime function or stub to call.
3835 int length = instr->hydrogen()->length(); 3933 int length = instr->hydrogen()->length();
3836 if (instr->hydrogen()->IsCopyOnWrite()) { 3934 if (instr->hydrogen()->IsCopyOnWrite()) {
3837 ASSERT(instr->hydrogen()->depth() == 1); 3935 ASSERT(instr->hydrogen()->depth() == 1);
3838 FastCloneShallowArrayStub::Mode mode = 3936 FastCloneShallowArrayStub::Mode mode =
3839 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS; 3937 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS;
3840 FastCloneShallowArrayStub stub(mode, length); 3938 FastCloneShallowArrayStub stub(mode, length);
3841 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 3939 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
3842 } else if (instr->hydrogen()->depth() > 1) { 3940 } else if (instr->hydrogen()->depth() > 1) {
3843 CallRuntime(Runtime::kCreateArrayLiteral, 3, instr); 3941 CallRuntime(Runtime::kCreateArrayLiteral, 3, instr);
3844 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { 3942 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
3845 CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr); 3943 CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr);
3846 } else { 3944 } else {
3847 FastCloneShallowArrayStub::Mode mode = 3945 FastCloneShallowArrayStub::Mode mode =
3848 FastCloneShallowArrayStub::CLONE_ELEMENTS; 3946 constant_elements_kind == FAST_DOUBLE_ELEMENTS
3947 ? FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS
3948 : FastCloneShallowArrayStub::CLONE_ELEMENTS;
3849 FastCloneShallowArrayStub stub(mode, length); 3949 FastCloneShallowArrayStub stub(mode, length);
3850 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 3950 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
3851 } 3951 }
3852 } 3952 }
3853 3953
3854 3954
3855 void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) { 3955 void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) {
3856 // Setup the parameters to the stub/runtime call. 3956 // Setup the parameters to the stub/runtime call.
3857 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 3957 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
3858 __ push(FieldOperand(rax, JSFunction::kLiteralsOffset)); 3958 __ push(FieldOperand(rax, JSFunction::kLiteralsOffset));
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
3927 } 4027 }
3928 } 4028 }
3929 4029
3930 4030
3931 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { 4031 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
3932 // Use the fast case closure allocation code that allocates in new 4032 // Use the fast case closure allocation code that allocates in new
3933 // space for nested functions that don't need literals cloning. 4033 // space for nested functions that don't need literals cloning.
3934 Handle<SharedFunctionInfo> shared_info = instr->shared_info(); 4034 Handle<SharedFunctionInfo> shared_info = instr->shared_info();
3935 bool pretenure = instr->hydrogen()->pretenure(); 4035 bool pretenure = instr->hydrogen()->pretenure();
3936 if (!pretenure && shared_info->num_literals() == 0) { 4036 if (!pretenure && shared_info->num_literals() == 0) {
3937 FastNewClosureStub stub( 4037 FastNewClosureStub stub(shared_info->strict_mode_flag());
3938 shared_info->strict_mode() ? kStrictMode : kNonStrictMode);
3939 __ Push(shared_info); 4038 __ Push(shared_info);
3940 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 4039 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
3941 } else { 4040 } else {
3942 __ push(rsi); 4041 __ push(rsi);
3943 __ Push(shared_info); 4042 __ Push(shared_info);
3944 __ PushRoot(pretenure ? 4043 __ PushRoot(pretenure ?
3945 Heap::kTrueValueRootIndex : 4044 Heap::kTrueValueRootIndex :
3946 Heap::kFalseValueRootIndex); 4045 Heap::kFalseValueRootIndex);
3947 CallRuntime(Runtime::kNewClosure, 3, instr); 4046 CallRuntime(Runtime::kNewClosure, 3, instr);
3948 } 4047 }
(...skipping 19 matching lines...) Expand all
3968 } 4067 }
3969 4068
3970 4069
3971 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { 4070 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
3972 Register input = ToRegister(instr->InputAt(0)); 4071 Register input = ToRegister(instr->InputAt(0));
3973 int true_block = chunk_->LookupDestination(instr->true_block_id()); 4072 int true_block = chunk_->LookupDestination(instr->true_block_id());
3974 int false_block = chunk_->LookupDestination(instr->false_block_id()); 4073 int false_block = chunk_->LookupDestination(instr->false_block_id());
3975 Label* true_label = chunk_->GetAssemblyLabel(true_block); 4074 Label* true_label = chunk_->GetAssemblyLabel(true_block);
3976 Label* false_label = chunk_->GetAssemblyLabel(false_block); 4075 Label* false_label = chunk_->GetAssemblyLabel(false_block);
3977 4076
3978 Condition final_branch_condition = EmitTypeofIs(true_label, 4077 Condition final_branch_condition =
3979 false_label, 4078 EmitTypeofIs(true_label, false_label, input, instr->type_literal());
3980 input, 4079 if (final_branch_condition != no_condition) {
3981 instr->type_literal()); 4080 EmitBranch(true_block, false_block, final_branch_condition);
3982 4081 }
3983 EmitBranch(true_block, false_block, final_branch_condition);
3984 } 4082 }
3985 4083
3986 4084
3987 Condition LCodeGen::EmitTypeofIs(Label* true_label, 4085 Condition LCodeGen::EmitTypeofIs(Label* true_label,
3988 Label* false_label, 4086 Label* false_label,
3989 Register input, 4087 Register input,
3990 Handle<String> type_name) { 4088 Handle<String> type_name) {
3991 Condition final_branch_condition = no_condition; 4089 Condition final_branch_condition = no_condition;
3992 if (type_name->Equals(heap()->number_symbol())) { 4090 if (type_name->Equals(heap()->number_symbol())) {
3993 __ JumpIfSmi(input, true_label); 4091 __ JumpIfSmi(input, true_label);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
4041 __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input); 4139 __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input);
4042 __ j(below, false_label); 4140 __ j(below, false_label);
4043 __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); 4141 __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
4044 __ j(above, false_label); 4142 __ j(above, false_label);
4045 // Check for undetectable objects => false. 4143 // Check for undetectable objects => false.
4046 __ testb(FieldOperand(input, Map::kBitFieldOffset), 4144 __ testb(FieldOperand(input, Map::kBitFieldOffset),
4047 Immediate(1 << Map::kIsUndetectable)); 4145 Immediate(1 << Map::kIsUndetectable));
4048 final_branch_condition = zero; 4146 final_branch_condition = zero;
4049 4147
4050 } else { 4148 } else {
4051 final_branch_condition = never;
4052 __ jmp(false_label); 4149 __ jmp(false_label);
4053 } 4150 }
4054 4151
4055 return final_branch_condition; 4152 return final_branch_condition;
4056 } 4153 }
4057 4154
4058 4155
4059 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { 4156 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
4060 Register temp = ToRegister(instr->TempAt(0)); 4157 Register temp = ToRegister(instr->TempAt(0));
4061 int true_block = chunk_->LookupDestination(instr->true_block_id()); 4158 int true_block = chunk_->LookupDestination(instr->true_block_id());
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
4196 RegisterEnvironmentForDeoptimization(environment); 4293 RegisterEnvironmentForDeoptimization(environment);
4197 ASSERT(osr_pc_offset_ == -1); 4294 ASSERT(osr_pc_offset_ == -1);
4198 osr_pc_offset_ = masm()->pc_offset(); 4295 osr_pc_offset_ = masm()->pc_offset();
4199 } 4296 }
4200 4297
4201 #undef __ 4298 #undef __
4202 4299
4203 } } // namespace v8::internal 4300 } } // namespace v8::internal
4204 4301
4205 #endif // V8_TARGET_ARCH_X64 4302 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/lithium-codegen-x64.h ('k') | src/x64/lithium-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698