| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 991 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1002 Handle<Object> value, | 1002 Handle<Object> value, |
| 1003 bool reversed, | 1003 bool reversed, |
| 1004 OverwriteMode overwrite_mode) { | 1004 OverwriteMode overwrite_mode) { |
| 1005 // NOTE: This is an attempt to inline (a bit) more of the code for | 1005 // NOTE: This is an attempt to inline (a bit) more of the code for |
| 1006 // some possible smi operations (like + and -) when (at least) one | 1006 // some possible smi operations (like + and -) when (at least) one |
| 1007 // of the operands is a literal smi. With this optimization, the | 1007 // of the operands is a literal smi. With this optimization, the |
| 1008 // performance of the system is increased by ~15%, and the generated | 1008 // performance of the system is increased by ~15%, and the generated |
| 1009 // code size is increased by ~1% (measured on a combination of | 1009 // code size is increased by ~1% (measured on a combination of |
| 1010 // different benchmarks). | 1010 // different benchmarks). |
| 1011 | 1011 |
| 1012 // TODO(1217802): Optimize some special cases of operations | 1012 // TODO(199): Optimize some special cases of operations involving a |
| 1013 // involving a smi literal (multiply by 2, shift by 0, etc.). | 1013 // smi literal (multiply by 2, shift by 0, etc.). |
| 1014 | 1014 |
| 1015 // Get the literal value. | 1015 // Get the literal value. |
| 1016 Smi* smi_value = Smi::cast(*value); | 1016 Smi* smi_value = Smi::cast(*value); |
| 1017 int int_value = smi_value->value(); | 1017 int int_value = smi_value->value(); |
| 1018 ASSERT(is_intn(int_value, kMaxSmiInlinedBits)); | 1018 ASSERT(is_intn(int_value, kMaxSmiInlinedBits)); |
| 1019 | 1019 |
| 1020 switch (op) { | 1020 switch (op) { |
| 1021 case Token::ADD: { | 1021 case Token::ADD: { |
| 1022 DeferredCode* deferred = NULL; | 1022 DeferredCode* deferred = NULL; |
| 1023 if (!reversed) { | 1023 if (!reversed) { |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1150 new DeferredInlinedSmiOperation(this, Token::SHL, smi_value, | 1150 new DeferredInlinedSmiOperation(this, Token::SHL, smi_value, |
| 1151 overwrite_mode); | 1151 overwrite_mode); |
| 1152 Result operand = frame_->Pop(); | 1152 Result operand = frame_->Pop(); |
| 1153 operand.ToRegister(); | 1153 operand.ToRegister(); |
| 1154 __ test(operand.reg(), Immediate(kSmiTagMask)); | 1154 __ test(operand.reg(), Immediate(kSmiTagMask)); |
| 1155 deferred->enter()->Branch(not_zero, &operand, not_taken); | 1155 deferred->enter()->Branch(not_zero, &operand, not_taken); |
| 1156 Result answer = allocator()->Allocate(); | 1156 Result answer = allocator()->Allocate(); |
| 1157 ASSERT(answer.is_valid()); | 1157 ASSERT(answer.is_valid()); |
| 1158 __ mov(answer.reg(), Operand(operand.reg())); | 1158 __ mov(answer.reg(), Operand(operand.reg())); |
| 1159 ASSERT(kSmiTag == 0); // adjust code if not the case | 1159 ASSERT(kSmiTag == 0); // adjust code if not the case |
| 1160 // We do no shifts, only the Smi conversion, if shift_value is 1. |
| 1160 if (shift_value == 0) { | 1161 if (shift_value == 0) { |
| 1161 __ sar(answer.reg(), kSmiTagSize); | 1162 __ sar(answer.reg(), kSmiTagSize); |
| 1162 } else if (shift_value > 1) { | 1163 } else if (shift_value > 1) { |
| 1163 __ shl(answer.reg(), shift_value - 1); | 1164 __ shl(answer.reg(), shift_value - 1); |
| 1164 } // We do no shifts, only the Smi conversion, if shift_value is 1. | 1165 } |
| 1165 // Convert int result to Smi, checking that it is in int range. | 1166 // Convert int result to Smi, checking that it is in int range. |
| 1166 ASSERT(kSmiTagSize == times_2); // adjust code if not the case | 1167 ASSERT(kSmiTagSize == times_2); // adjust code if not the case |
| 1167 __ add(answer.reg(), Operand(answer.reg())); | 1168 __ add(answer.reg(), Operand(answer.reg())); |
| 1168 deferred->enter()->Branch(overflow, &operand, not_taken); | 1169 deferred->enter()->Branch(overflow, &operand, not_taken); |
| 1169 operand.Unuse(); | 1170 operand.Unuse(); |
| 1170 deferred->exit()->Bind(&answer); | 1171 deferred->exit()->Bind(&answer); |
| 1171 frame_->Push(&answer); | 1172 frame_->Push(&answer); |
| 1172 } | 1173 } |
| 1173 break; | 1174 break; |
| 1174 } | 1175 } |
| (...skipping 1813 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2988 | 2989 |
| 2989 // Push the literal. | 2990 // Push the literal. |
| 2990 frame_->EmitPush(ebx); | 2991 frame_->EmitPush(ebx); |
| 2991 // Clone the boilerplate object. | 2992 // Clone the boilerplate object. |
| 2992 frame_->CallRuntime(Runtime::kCloneObjectLiteralBoilerplate, 1); | 2993 frame_->CallRuntime(Runtime::kCloneObjectLiteralBoilerplate, 1); |
| 2993 // Push the new cloned literal object as the result. | 2994 // Push the new cloned literal object as the result. |
| 2994 frame_->EmitPush(eax); | 2995 frame_->EmitPush(eax); |
| 2995 | 2996 |
| 2996 | 2997 |
| 2997 for (int i = 0; i < node->properties()->length(); i++) { | 2998 for (int i = 0; i < node->properties()->length(); i++) { |
| 2998 ObjectLiteral::Property* property = node->properties()->at(i); | 2999 ObjectLiteral::Property* property = node->properties()->at(i); |
| 2999 switch (property->kind()) { | 3000 switch (property->kind()) { |
| 3000 case ObjectLiteral::Property::CONSTANT: break; | 3001 case ObjectLiteral::Property::CONSTANT: break; |
| 3001 case ObjectLiteral::Property::COMPUTED: { | 3002 case ObjectLiteral::Property::COMPUTED: { |
| 3002 Handle<Object> key(property->key()->handle()); | 3003 Handle<Object> key(property->key()->handle()); |
| 3003 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 3004 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 3004 if (key->IsSymbol()) { | 3005 if (key->IsSymbol()) { |
| 3005 __ mov(eax, frame_->Top()); | 3006 __ mov(eax, frame_->Top()); |
| 3006 frame_->EmitPush(eax); | 3007 frame_->EmitPush(eax); |
| 3007 LoadAndSpill(property->value()); | 3008 LoadAndSpill(property->value()); |
| 3008 frame_->EmitPop(eax); | 3009 frame_->EmitPop(eax); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3091 int offset = i * kPointerSize + Array::kHeaderSize; | 3092 int offset = i * kPointerSize + Array::kHeaderSize; |
| 3092 __ mov(FieldOperand(ecx, offset), eax); | 3093 __ mov(FieldOperand(ecx, offset), eax); |
| 3093 | 3094 |
| 3094 // Update the write barrier for the array address. | 3095 // Update the write barrier for the array address. |
| 3095 __ RecordWrite(ecx, offset, eax, ebx); | 3096 __ RecordWrite(ecx, offset, eax, ebx); |
| 3096 } | 3097 } |
| 3097 } | 3098 } |
| 3098 } | 3099 } |
| 3099 | 3100 |
| 3100 | 3101 |
| 3102 void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) { |
| 3103 // Call runtime routine to allocate the catch extension object and |
| 3104 // assign the exception value to the catch variable. |
| 3105 Comment cmnt(masm_, "[CatchExtensionObject "); |
| 3106 Load(node->key()); |
| 3107 Load(node->value()); |
| 3108 __ CallRuntime(Runtime::kCreateCatchExtensionObject, 2); |
| 3109 frame_->Push(eax); |
| 3110 } |
| 3111 |
| 3112 |
| 3101 bool CodeGenerator::IsInlineSmi(Literal* literal) { | 3113 bool CodeGenerator::IsInlineSmi(Literal* literal) { |
| 3102 if (literal == NULL || !literal->handle()->IsSmi()) return false; | 3114 if (literal == NULL || !literal->handle()->IsSmi()) return false; |
| 3103 int int_value = Smi::cast(*literal->handle())->value(); | 3115 int int_value = Smi::cast(*literal->handle())->value(); |
| 3104 return is_intn(int_value, kMaxSmiInlinedBits); | 3116 return is_intn(int_value, kMaxSmiInlinedBits); |
| 3105 } | 3117 } |
| 3106 | 3118 |
| 3107 | 3119 |
| 3108 void CodeGenerator::VisitAssignment(Assignment* node) { | 3120 void CodeGenerator::VisitAssignment(Assignment* node) { |
| 3109 Comment cmnt(masm_, "[ Assignment"); | 3121 Comment cmnt(masm_, "[ Assignment"); |
| 3110 CodeForStatementPosition(node); | 3122 CodeForStatementPosition(node); |
| (...skipping 2060 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5171 // - 0x80000000: high bit would be lost when smi tagging. | 5183 // - 0x80000000: high bit would be lost when smi tagging. |
| 5172 // - 0x40000000: this number would convert to negative when | 5184 // - 0x40000000: this number would convert to negative when |
| 5173 // Smi tagging these two cases can only happen with shifts | 5185 // Smi tagging these two cases can only happen with shifts |
| 5174 // by 0 or 1 when handed a valid smi. | 5186 // by 0 or 1 when handed a valid smi. |
| 5175 __ test(eax, Immediate(0xc0000000)); | 5187 __ test(eax, Immediate(0xc0000000)); |
| 5176 __ j(not_zero, slow, not_taken); | 5188 __ j(not_zero, slow, not_taken); |
| 5177 break; | 5189 break; |
| 5178 case Token::SHL: | 5190 case Token::SHL: |
| 5179 __ shl(eax); | 5191 __ shl(eax); |
| 5180 // Check that the *signed* result fits in a smi. | 5192 // Check that the *signed* result fits in a smi. |
| 5181 __ lea(ecx, Operand(eax, 0x40000000)); | 5193 __ cmp(eax, 0xc0000000); |
| 5182 __ test(ecx, Immediate(0x80000000)); | 5194 __ j(sign, slow, not_taken); |
| 5183 __ j(not_zero, slow, not_taken); | |
| 5184 break; | 5195 break; |
| 5185 default: | 5196 default: |
| 5186 UNREACHABLE(); | 5197 UNREACHABLE(); |
| 5187 } | 5198 } |
| 5188 // Tag the result and store it in register eax. | 5199 // Tag the result and store it in register eax. |
| 5189 ASSERT(kSmiTagSize == times_2); // adjust code if not the case | 5200 ASSERT(kSmiTagSize == times_2); // adjust code if not the case |
| 5190 __ lea(eax, Operand(eax, eax, times_1, kSmiTag)); | 5201 __ lea(eax, Operand(eax, eax, times_1, kSmiTag)); |
| 5191 break; | 5202 break; |
| 5192 | 5203 |
| 5193 default: | 5204 default: |
| (...skipping 1019 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6213 | 6224 |
| 6214 // Slow-case: Go through the JavaScript implementation. | 6225 // Slow-case: Go through the JavaScript implementation. |
| 6215 __ bind(&slow); | 6226 __ bind(&slow); |
| 6216 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 6227 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
| 6217 } | 6228 } |
| 6218 | 6229 |
| 6219 | 6230 |
| 6220 #undef __ | 6231 #undef __ |
| 6221 | 6232 |
| 6222 } } // namespace v8::internal | 6233 } } // namespace v8::internal |
| OLD | NEW |