OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 2020 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2031 String::cast(*right_side.handle())->length() == 1 && | 2031 String::cast(*right_side.handle())->length() == 1 && |
2032 String::cast(*right_side.handle())->IsAsciiRepresentation()); | 2032 String::cast(*right_side.handle())->IsAsciiRepresentation()); |
2033 } | 2033 } |
2034 | 2034 |
2035 if (left_side_constant_smi || right_side_constant_smi) { | 2035 if (left_side_constant_smi || right_side_constant_smi) { |
2036 bool is_loop_condition = (node->AsExpression() != NULL) && | 2036 bool is_loop_condition = (node->AsExpression() != NULL) && |
2037 node->AsExpression()->is_loop_condition(); | 2037 node->AsExpression()->is_loop_condition(); |
2038 ConstantSmiComparison(cc, strict, dest, &left_side, &right_side, | 2038 ConstantSmiComparison(cc, strict, dest, &left_side, &right_side, |
2039 left_side_constant_smi, right_side_constant_smi, | 2039 left_side_constant_smi, right_side_constant_smi, |
2040 is_loop_condition); | 2040 is_loop_condition); |
2041 } else if (cc == equal && | |
2042 (left_side_constant_null || right_side_constant_null)) { | |
2043 // To make null checks efficient, we check if either the left side or | |
2044 // the right side is the constant 'null'. | |
2045 // If so, we optimize the code by inlining a null check instead of | |
2046 // calling the (very) general runtime routine for checking equality. | |
2047 Result operand = left_side_constant_null ? right_side : left_side; | |
2048 right_side.Unuse(); | |
2049 left_side.Unuse(); | |
2050 operand.ToRegister(); | |
2051 __ CompareRoot(operand.reg(), Heap::kNullValueRootIndex); | |
2052 if (strict) { | |
2053 operand.Unuse(); | |
2054 dest->Split(equal); | |
2055 } else { | |
2056 // The 'null' value is only equal to 'undefined' if using non-strict | |
2057 // comparisons. | |
2058 dest->true_target()->Branch(equal); | |
2059 __ CompareRoot(operand.reg(), Heap::kUndefinedValueRootIndex); | |
2060 dest->true_target()->Branch(equal); | |
2061 Condition is_smi = masm_->CheckSmi(operand.reg()); | |
2062 dest->false_target()->Branch(is_smi); | |
2063 | |
2064 // It can be an undetectable object. | |
2065 // Use a scratch register in preference to spilling operand.reg(). | |
2066 Result temp = allocator()->Allocate(); | |
2067 ASSERT(temp.is_valid()); | |
2068 __ movq(temp.reg(), | |
2069 FieldOperand(operand.reg(), HeapObject::kMapOffset)); | |
2070 __ testb(FieldOperand(temp.reg(), Map::kBitFieldOffset), | |
2071 Immediate(1 << Map::kIsUndetectable)); | |
2072 temp.Unuse(); | |
2073 operand.Unuse(); | |
2074 dest->Split(not_zero); | |
2075 } | |
2076 } else if (left_side_constant_1_char_string || | 2041 } else if (left_side_constant_1_char_string || |
2077 right_side_constant_1_char_string) { | 2042 right_side_constant_1_char_string) { |
2078 if (left_side_constant_1_char_string && right_side_constant_1_char_string) { | 2043 if (left_side_constant_1_char_string && right_side_constant_1_char_string) { |
2079 // Trivial case, comparing two constants. | 2044 // Trivial case, comparing two constants. |
2080 int left_value = String::cast(*left_side.handle())->Get(0); | 2045 int left_value = String::cast(*left_side.handle())->Get(0); |
2081 int right_value = String::cast(*right_side.handle())->Get(0); | 2046 int right_value = String::cast(*right_side.handle())->Get(0); |
2082 switch (cc) { | 2047 switch (cc) { |
2083 case less: | 2048 case less: |
2084 dest->Goto(left_value < right_value); | 2049 dest->Goto(left_value < right_value); |
2085 break; | 2050 break; |
(...skipping 3003 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5089 // For a compound assignment the right-hand side is a binary operation | 5054 // For a compound assignment the right-hand side is a binary operation |
5090 // between the current property value and the actual right-hand side. | 5055 // between the current property value and the actual right-hand side. |
5091 LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); | 5056 LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); |
5092 Load(node->value()); | 5057 Load(node->value()); |
5093 | 5058 |
5094 // Perform the binary operation. | 5059 // Perform the binary operation. |
5095 bool overwrite_value = | 5060 bool overwrite_value = |
5096 (node->value()->AsBinaryOperation() != NULL && | 5061 (node->value()->AsBinaryOperation() != NULL && |
5097 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); | 5062 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); |
5098 // Construct the implicit binary operation. | 5063 // Construct the implicit binary operation. |
5099 BinaryOperation expr(node, node->binary_op(), node->target(), | 5064 BinaryOperation expr(node->binary_op(), node->target(), node->value()); |
5100 node->value()); | 5065 expr.CopyAnalysisResultsFrom(node); |
5101 GenericBinaryOperation(&expr, | 5066 GenericBinaryOperation(&expr, |
5102 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); | 5067 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); |
5103 } else { | 5068 } else { |
5104 // For non-compound assignment just load the right-hand side. | 5069 // For non-compound assignment just load the right-hand side. |
5105 Load(node->value()); | 5070 Load(node->value()); |
5106 } | 5071 } |
5107 | 5072 |
5108 // Perform the assignment. | 5073 // Perform the assignment. |
5109 if (var->mode() != Variable::CONST || node->op() == Token::INIT_CONST) { | 5074 if (var->mode() != Variable::CONST || node->op() == Token::INIT_CONST) { |
5110 CodeForSourcePosition(node->position()); | 5075 CodeForSourcePosition(node->position()); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5181 frame()->Dup(); | 5146 frame()->Dup(); |
5182 } | 5147 } |
5183 Result value = EmitNamedLoad(name, var != NULL); | 5148 Result value = EmitNamedLoad(name, var != NULL); |
5184 frame()->Push(&value); | 5149 frame()->Push(&value); |
5185 Load(node->value()); | 5150 Load(node->value()); |
5186 | 5151 |
5187 bool overwrite_value = | 5152 bool overwrite_value = |
5188 (node->value()->AsBinaryOperation() != NULL && | 5153 (node->value()->AsBinaryOperation() != NULL && |
5189 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); | 5154 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); |
5190 // Construct the implicit binary operation. | 5155 // Construct the implicit binary operation. |
5191 BinaryOperation expr(node, node->binary_op(), node->target(), | 5156 BinaryOperation expr(node->binary_op(), node->target(), node->value()); |
5192 node->value()); | 5157 expr.CopyAnalysisResultsFrom(node); |
5193 GenericBinaryOperation(&expr, | 5158 GenericBinaryOperation(&expr, |
5194 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); | 5159 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); |
5195 } else { | 5160 } else { |
5196 // For non-compound assignment just load the right-hand side. | 5161 // For non-compound assignment just load the right-hand side. |
5197 Load(node->value()); | 5162 Load(node->value()); |
5198 } | 5163 } |
5199 | 5164 |
5200 // Stack layout: | 5165 // Stack layout: |
5201 // [tos] : value | 5166 // [tos] : value |
5202 // [tos+1] : receiver (only materialized if non-trivial) | 5167 // [tos+1] : receiver (only materialized if non-trivial) |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5283 frame()->PushElementAt(1); | 5248 frame()->PushElementAt(1); |
5284 frame()->PushElementAt(1); | 5249 frame()->PushElementAt(1); |
5285 Result value = EmitKeyedLoad(); | 5250 Result value = EmitKeyedLoad(); |
5286 frame()->Push(&value); | 5251 frame()->Push(&value); |
5287 Load(node->value()); | 5252 Load(node->value()); |
5288 | 5253 |
5289 // Perform the binary operation. | 5254 // Perform the binary operation. |
5290 bool overwrite_value = | 5255 bool overwrite_value = |
5291 (node->value()->AsBinaryOperation() != NULL && | 5256 (node->value()->AsBinaryOperation() != NULL && |
5292 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); | 5257 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); |
5293 BinaryOperation expr(node, node->binary_op(), node->target(), | 5258 BinaryOperation expr(node->binary_op(), node->target(), node->value()); |
5294 node->value()); | 5259 expr.CopyAnalysisResultsFrom(node); |
5295 GenericBinaryOperation(&expr, | 5260 GenericBinaryOperation(&expr, |
5296 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); | 5261 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); |
5297 } else { | 5262 } else { |
5298 // For non-compound assignment just load the right-hand side. | 5263 // For non-compound assignment just load the right-hand side. |
5299 Load(node->value()); | 5264 Load(node->value()); |
5300 } | 5265 } |
5301 | 5266 |
5302 // Stack layout: | 5267 // Stack layout: |
5303 // [tos] : value | 5268 // [tos] : value |
5304 // [tos+1] : key | 5269 // [tos+1] : key |
(...skipping 2743 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8048 frame_->Push(&right_result); | 8013 frame_->Push(&right_result); |
8049 } else { | 8014 } else { |
8050 Load(left); | 8015 Load(left); |
8051 Load(right); | 8016 Load(right); |
8052 } | 8017 } |
8053 | 8018 |
8054 Comparison(node, cc, strict, destination()); | 8019 Comparison(node, cc, strict, destination()); |
8055 } | 8020 } |
8056 | 8021 |
8057 | 8022 |
| 8023 void CodeGenerator::VisitCompareToNull(CompareToNull* node) { |
| 8024 Comment cmnt(masm_, "[ CompareToNull"); |
| 8025 |
| 8026 Load(node->expression()); |
| 8027 Result operand = frame_->Pop(); |
| 8028 operand.ToRegister(); |
| 8029 __ CompareRoot(operand.reg(), Heap::kNullValueRootIndex); |
| 8030 if (node->is_strict()) { |
| 8031 operand.Unuse(); |
| 8032 destination()->Split(equal); |
| 8033 } else { |
| 8034 // The 'null' value is only equal to 'undefined' if using non-strict |
| 8035 // comparisons. |
| 8036 destination()->true_target()->Branch(equal); |
| 8037 __ CompareRoot(operand.reg(), Heap::kUndefinedValueRootIndex); |
| 8038 destination()->true_target()->Branch(equal); |
| 8039 Condition is_smi = masm_->CheckSmi(operand.reg()); |
| 8040 destination()->false_target()->Branch(is_smi); |
| 8041 |
| 8042 // It can be an undetectable object. |
| 8043 // Use a scratch register in preference to spilling operand.reg(). |
| 8044 Result temp = allocator()->Allocate(); |
| 8045 ASSERT(temp.is_valid()); |
| 8046 __ movq(temp.reg(), |
| 8047 FieldOperand(operand.reg(), HeapObject::kMapOffset)); |
| 8048 __ testb(FieldOperand(temp.reg(), Map::kBitFieldOffset), |
| 8049 Immediate(1 << Map::kIsUndetectable)); |
| 8050 temp.Unuse(); |
| 8051 operand.Unuse(); |
| 8052 destination()->Split(not_zero); |
| 8053 } |
| 8054 } |
| 8055 |
| 8056 |
8058 #ifdef DEBUG | 8057 #ifdef DEBUG |
8059 bool CodeGenerator::HasValidEntryRegisters() { | 8058 bool CodeGenerator::HasValidEntryRegisters() { |
8060 return (allocator()->count(rax) == (frame()->is_used(rax) ? 1 : 0)) | 8059 return (allocator()->count(rax) == (frame()->is_used(rax) ? 1 : 0)) |
8061 && (allocator()->count(rbx) == (frame()->is_used(rbx) ? 1 : 0)) | 8060 && (allocator()->count(rbx) == (frame()->is_used(rbx) ? 1 : 0)) |
8062 && (allocator()->count(rcx) == (frame()->is_used(rcx) ? 1 : 0)) | 8061 && (allocator()->count(rcx) == (frame()->is_used(rcx) ? 1 : 0)) |
8063 && (allocator()->count(rdx) == (frame()->is_used(rdx) ? 1 : 0)) | 8062 && (allocator()->count(rdx) == (frame()->is_used(rdx) ? 1 : 0)) |
8064 && (allocator()->count(rdi) == (frame()->is_used(rdi) ? 1 : 0)) | 8063 && (allocator()->count(rdi) == (frame()->is_used(rdi) ? 1 : 0)) |
8065 && (allocator()->count(r8) == (frame()->is_used(r8) ? 1 : 0)) | 8064 && (allocator()->count(r8) == (frame()->is_used(r8) ? 1 : 0)) |
8066 && (allocator()->count(r9) == (frame()->is_used(r9) ? 1 : 0)) | 8065 && (allocator()->count(r9) == (frame()->is_used(r9) ? 1 : 0)) |
8067 && (allocator()->count(r11) == (frame()->is_used(r11) ? 1 : 0)) | 8066 && (allocator()->count(r11) == (frame()->is_used(r11) ? 1 : 0)) |
(...skipping 4791 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12859 #undef __ | 12858 #undef __ |
12860 | 12859 |
12861 void RecordWriteStub::Generate(MacroAssembler* masm) { | 12860 void RecordWriteStub::Generate(MacroAssembler* masm) { |
12862 masm->RecordWriteHelper(object_, addr_, scratch_); | 12861 masm->RecordWriteHelper(object_, addr_, scratch_); |
12863 masm->ret(0); | 12862 masm->ret(0); |
12864 } | 12863 } |
12865 | 12864 |
12866 } } // namespace v8::internal | 12865 } } // namespace v8::internal |
12867 | 12866 |
12868 #endif // V8_TARGET_ARCH_X64 | 12867 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |