| 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 3099 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   3110       case Token::NOT: |   3110       case Token::NOT: | 
|   3111       case Token::DELETE: |   3111       case Token::DELETE: | 
|   3112       case Token::TYPEOF: |   3112       case Token::TYPEOF: | 
|   3113         UNREACHABLE();  // handled above |   3113         UNREACHABLE();  // handled above | 
|   3114         break; |   3114         break; | 
|   3115  |   3115  | 
|   3116       case Token::SUB: { |   3116       case Token::SUB: { | 
|   3117         GenericUnaryOpStub stub(Token::SUB, overwrite); |   3117         GenericUnaryOpStub stub(Token::SUB, overwrite); | 
|   3118         Result operand = frame_->Pop(); |   3118         Result operand = frame_->Pop(); | 
|   3119         Result answer = frame_->CallStub(&stub, &operand); |   3119         Result answer = frame_->CallStub(&stub, &operand); | 
 |   3120         answer.set_type_info(TypeInfo::Number()); | 
|   3120         frame_->Push(&answer); |   3121         frame_->Push(&answer); | 
|   3121         break; |   3122         break; | 
|   3122       } |   3123       } | 
|   3123  |   3124  | 
|   3124       case Token::BIT_NOT: { |   3125       case Token::BIT_NOT: { | 
|   3125         // Smi check. |   3126         // Smi check. | 
|   3126         JumpTarget smi_label; |   3127         JumpTarget smi_label; | 
|   3127         JumpTarget continue_label; |   3128         JumpTarget continue_label; | 
|   3128         Result operand = frame_->Pop(); |   3129         Result operand = frame_->Pop(); | 
|   3129         operand.ToRegister(); |   3130         operand.ToRegister(); | 
|   3130  |   3131  | 
|   3131         Condition is_smi = masm_->CheckSmi(operand.reg()); |   3132         Condition is_smi = masm_->CheckSmi(operand.reg()); | 
|   3132         smi_label.Branch(is_smi, &operand); |   3133         smi_label.Branch(is_smi, &operand); | 
|   3133  |   3134  | 
|   3134         GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); |   3135         GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); | 
|   3135         Result answer = frame_->CallStub(&stub, &operand); |   3136         Result answer = frame_->CallStub(&stub, &operand); | 
|   3136         continue_label.Jump(&answer); |   3137         continue_label.Jump(&answer); | 
|   3137  |   3138  | 
|   3138         smi_label.Bind(&answer); |   3139         smi_label.Bind(&answer); | 
|   3139         answer.ToRegister(); |   3140         answer.ToRegister(); | 
|   3140         frame_->Spill(answer.reg()); |   3141         frame_->Spill(answer.reg()); | 
|   3141         __ SmiNot(answer.reg(), answer.reg()); |   3142         __ SmiNot(answer.reg(), answer.reg()); | 
|   3142         continue_label.Bind(&answer); |   3143         continue_label.Bind(&answer); | 
 |   3144         answer.set_type_info(TypeInfo::Smi()); | 
|   3143         frame_->Push(&answer); |   3145         frame_->Push(&answer); | 
|   3144         break; |   3146         break; | 
|   3145       } |   3147       } | 
|   3146  |   3148  | 
|   3147       case Token::ADD: { |   3149       case Token::ADD: { | 
|   3148         // Smi check. |   3150         // Smi check. | 
|   3149         JumpTarget continue_label; |   3151         JumpTarget continue_label; | 
|   3150         Result operand = frame_->Pop(); |   3152         Result operand = frame_->Pop(); | 
 |   3153         TypeInfo operand_info = operand.type_info(); | 
|   3151         operand.ToRegister(); |   3154         operand.ToRegister(); | 
|   3152         Condition is_smi = masm_->CheckSmi(operand.reg()); |   3155         Condition is_smi = masm_->CheckSmi(operand.reg()); | 
|   3153         continue_label.Branch(is_smi, &operand); |   3156         continue_label.Branch(is_smi, &operand); | 
|   3154         frame_->Push(&operand); |   3157         frame_->Push(&operand); | 
|   3155         Result answer = frame_->InvokeBuiltin(Builtins::TO_NUMBER, |   3158         Result answer = frame_->InvokeBuiltin(Builtins::TO_NUMBER, | 
|   3156                                               CALL_FUNCTION, 1); |   3159                                               CALL_FUNCTION, 1); | 
|   3157  |   3160  | 
|   3158         continue_label.Bind(&answer); |   3161         continue_label.Bind(&answer); | 
 |   3162         if (operand_info.IsSmi()) { | 
 |   3163           answer.set_type_info(TypeInfo::Smi()); | 
 |   3164         } else if (operand_info.IsInteger32()) { | 
 |   3165           answer.set_type_info(TypeInfo::Integer32()); | 
 |   3166         } else { | 
 |   3167           answer.set_type_info(TypeInfo::Number()); | 
 |   3168         } | 
|   3159         frame_->Push(&answer); |   3169         frame_->Push(&answer); | 
|   3160         break; |   3170         break; | 
|   3161       } |   3171       } | 
|   3162  |  | 
|   3163       default: |   3172       default: | 
|   3164         UNREACHABLE(); |   3173         UNREACHABLE(); | 
|   3165     } |   3174     } | 
|   3166   } |   3175   } | 
|   3167 } |   3176 } | 
|   3168  |   3177  | 
|   3169  |   3178  | 
|   3170 // The value in dst was optimistically incremented or decremented. |   3179 // The value in dst was optimistically incremented or decremented. | 
|   3171 // The result overflowed or was not smi tagged.  Call into the runtime |   3180 // The result overflowed or was not smi tagged.  Call into the runtime | 
|   3172 // to convert the argument to a number, and call the specialized add |   3181 // to convert the argument to a number, and call the specialized add | 
| (...skipping 2540 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   5713 }; |   5722 }; | 
|   5714  |   5723  | 
|   5715  |   5724  | 
|   5716 void DeferredInlineBinaryOperation::Generate() { |   5725 void DeferredInlineBinaryOperation::Generate() { | 
|   5717   GenericBinaryOpStub stub(op_, mode_, NO_SMI_CODE_IN_STUB); |   5726   GenericBinaryOpStub stub(op_, mode_, NO_SMI_CODE_IN_STUB); | 
|   5718   stub.GenerateCall(masm_, left_, right_); |   5727   stub.GenerateCall(masm_, left_, right_); | 
|   5719   if (!dst_.is(rax)) __ movq(dst_, rax); |   5728   if (!dst_.is(rax)) __ movq(dst_, rax); | 
|   5720 } |   5729 } | 
|   5721  |   5730  | 
|   5722  |   5731  | 
 |   5732 static TypeInfo CalculateTypeInfo(TypeInfo operands_type, | 
 |   5733                                   Token::Value op, | 
 |   5734                                   const Result& right, | 
 |   5735                                   const Result& left) { | 
 |   5736   // Set TypeInfo of result according to the operation performed. | 
 |   5737   // We rely on the fact that smis have a 32 bit payload on x64. | 
 |   5738   STATIC_ASSERT(kSmiValueSize == 32); | 
 |   5739   switch (op) { | 
 |   5740     case Token::COMMA: | 
 |   5741       return right.type_info(); | 
 |   5742     case Token::OR: | 
 |   5743     case Token::AND: | 
 |   5744       // Result type can be either of the two input types. | 
 |   5745       return operands_type; | 
 |   5746     case Token::BIT_OR: | 
 |   5747     case Token::BIT_XOR: | 
 |   5748     case Token::BIT_AND: | 
 |   5749       // Result is always a smi. | 
 |   5750       return TypeInfo::Smi(); | 
 |   5751     case Token::SAR: | 
 |   5752     case Token::SHL: | 
 |   5753       // Result is always a smi. | 
 |   5754       return TypeInfo::Smi(); | 
 |   5755     case Token::SHR: | 
 |   5756       // Result of x >>> y is always a smi if masked y >= 1, otherwise a number. | 
 |   5757       return (right.is_constant() && right.handle()->IsSmi() | 
 |   5758                      && (Smi::cast(*right.handle())->value() & 0x1F) >= 1) | 
 |   5759           ? TypeInfo::Smi() | 
 |   5760           : TypeInfo::Number(); | 
 |   5761     case Token::ADD: | 
 |   5762       if (operands_type.IsNumber()) { | 
 |   5763         return TypeInfo::Number(); | 
 |   5764       } else if (left.type_info().IsString() || right.type_info().IsString()) { | 
 |   5765         return TypeInfo::String(); | 
 |   5766       } else { | 
 |   5767         return TypeInfo::Unknown(); | 
 |   5768       } | 
 |   5769     case Token::SUB: | 
 |   5770     case Token::MUL: | 
 |   5771     case Token::DIV: | 
 |   5772     case Token::MOD: | 
 |   5773       // Result is always a number. | 
 |   5774       return TypeInfo::Number(); | 
 |   5775     default: | 
 |   5776       UNREACHABLE(); | 
 |   5777   } | 
 |   5778   UNREACHABLE(); | 
 |   5779   return TypeInfo::Unknown(); | 
 |   5780 } | 
 |   5781  | 
 |   5782  | 
|   5723 void CodeGenerator::GenericBinaryOperation(Token::Value op, |   5783 void CodeGenerator::GenericBinaryOperation(Token::Value op, | 
|   5724                                            StaticType* type, |   5784                                            StaticType* type, | 
|   5725                                            OverwriteMode overwrite_mode) { |   5785                                            OverwriteMode overwrite_mode) { | 
|   5726   Comment cmnt(masm_, "[ BinaryOperation"); |   5786   Comment cmnt(masm_, "[ BinaryOperation"); | 
|   5727   Comment cmnt_token(masm_, Token::String(op)); |   5787   Comment cmnt_token(masm_, Token::String(op)); | 
|   5728  |   5788  | 
|   5729   if (op == Token::COMMA) { |   5789   if (op == Token::COMMA) { | 
|   5730     // Simply discard left value. |   5790     // Simply discard left value. | 
|   5731     frame_->Nip(1); |   5791     frame_->Nip(1); | 
|   5732     return; |   5792     return; | 
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   5778     // Compute the constant result at compile time, and leave it on the frame. |   5838     // Compute the constant result at compile time, and leave it on the frame. | 
|   5779     int left_int = Smi::cast(*left.handle())->value(); |   5839     int left_int = Smi::cast(*left.handle())->value(); | 
|   5780     int right_int = Smi::cast(*right.handle())->value(); |   5840     int right_int = Smi::cast(*right.handle())->value(); | 
|   5781     if (FoldConstantSmis(op, left_int, right_int)) return; |   5841     if (FoldConstantSmis(op, left_int, right_int)) return; | 
|   5782   } |   5842   } | 
|   5783  |   5843  | 
|   5784   // Get number type of left and right sub-expressions. |   5844   // Get number type of left and right sub-expressions. | 
|   5785   TypeInfo operands_type = |   5845   TypeInfo operands_type = | 
|   5786       TypeInfo::Combine(left.type_info(), right.type_info()); |   5846       TypeInfo::Combine(left.type_info(), right.type_info()); | 
|   5787  |   5847  | 
 |   5848   TypeInfo result_type = CalculateTypeInfo(operands_type, op, right, left); | 
 |   5849  | 
|   5788   Result answer; |   5850   Result answer; | 
|   5789   if (left_is_non_smi_constant || right_is_non_smi_constant) { |   5851   if (left_is_non_smi_constant || right_is_non_smi_constant) { | 
|   5790     GenericBinaryOpStub stub(op, |   5852     GenericBinaryOpStub stub(op, | 
|   5791                              overwrite_mode, |   5853                              overwrite_mode, | 
|   5792                              NO_SMI_CODE_IN_STUB, |   5854                              NO_SMI_CODE_IN_STUB, | 
|   5793                              operands_type); |   5855                              operands_type); | 
|   5794     answer = stub.GenerateCall(masm_, frame_, &left, &right); |   5856     answer = stub.GenerateCall(masm_, frame_, &left, &right); | 
|   5795   } else if (right_is_smi_constant) { |   5857   } else if (right_is_smi_constant) { | 
|   5796     answer = ConstantSmiBinaryOperation(op, &left, right.handle(), |   5858     answer = ConstantSmiBinaryOperation(op, &left, right.handle(), | 
|   5797                                         type, false, overwrite_mode); |   5859                                         type, false, overwrite_mode); | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
|   5808       answer = LikelySmiBinaryOperation(op, &left, &right, overwrite_mode); |   5870       answer = LikelySmiBinaryOperation(op, &left, &right, overwrite_mode); | 
|   5809     } else { |   5871     } else { | 
|   5810       GenericBinaryOpStub stub(op, |   5872       GenericBinaryOpStub stub(op, | 
|   5811                                overwrite_mode, |   5873                                overwrite_mode, | 
|   5812                                NO_GENERIC_BINARY_FLAGS, |   5874                                NO_GENERIC_BINARY_FLAGS, | 
|   5813                                operands_type); |   5875                                operands_type); | 
|   5814       answer = stub.GenerateCall(masm_, frame_, &left, &right); |   5876       answer = stub.GenerateCall(masm_, frame_, &left, &right); | 
|   5815     } |   5877     } | 
|   5816   } |   5878   } | 
|   5817  |   5879  | 
|   5818   // Set TypeInfo of result according to the operation performed. |  | 
|   5819   // We rely on the fact that smis have a 32 bit payload on x64. |  | 
|   5820   ASSERT(kSmiValueSize == 32); |  | 
|   5821   TypeInfo result_type = TypeInfo::Unknown(); |  | 
|   5822   switch (op) { |  | 
|   5823     case Token::COMMA: |  | 
|   5824       result_type = right.type_info(); |  | 
|   5825       break; |  | 
|   5826     case Token::OR: |  | 
|   5827     case Token::AND: |  | 
|   5828       // Result type can be either of the two input types. |  | 
|   5829       result_type = operands_type; |  | 
|   5830       break; |  | 
|   5831     case Token::BIT_OR: |  | 
|   5832     case Token::BIT_XOR: |  | 
|   5833     case Token::BIT_AND: |  | 
|   5834       // Result is always a smi. |  | 
|   5835       result_type = TypeInfo::Smi(); |  | 
|   5836       break; |  | 
|   5837     case Token::SAR: |  | 
|   5838     case Token::SHL: |  | 
|   5839       // Result is always a smi. |  | 
|   5840       result_type = TypeInfo::Smi(); |  | 
|   5841       break; |  | 
|   5842     case Token::SHR: |  | 
|   5843       // Result of x >>> y is always a smi if masked y >= 1, otherwise a number. |  | 
|   5844       result_type = (right.is_constant() && right.handle()->IsSmi() |  | 
|   5845                      && (Smi::cast(*right.handle())->value() & 0x1F) >= 1) |  | 
|   5846           ? TypeInfo::Smi() |  | 
|   5847           : TypeInfo::Number(); |  | 
|   5848       break; |  | 
|   5849     case Token::ADD: |  | 
|   5850       if (operands_type.IsNumber()) { |  | 
|   5851         result_type = TypeInfo::Number(); |  | 
|   5852       } else if (operands_type.IsString()) { |  | 
|   5853         result_type = TypeInfo::String(); |  | 
|   5854       } else { |  | 
|   5855         result_type = TypeInfo::Unknown(); |  | 
|   5856       } |  | 
|   5857       break; |  | 
|   5858     case Token::SUB: |  | 
|   5859     case Token::MUL: |  | 
|   5860     case Token::DIV: |  | 
|   5861     case Token::MOD: |  | 
|   5862       // Result is always a number. |  | 
|   5863       result_type = TypeInfo::Number(); |  | 
|   5864       break; |  | 
|   5865     default: |  | 
|   5866       UNREACHABLE(); |  | 
|   5867   } |  | 
|   5868   answer.set_type_info(result_type); |   5880   answer.set_type_info(result_type); | 
|   5869   frame_->Push(&answer); |   5881   frame_->Push(&answer); | 
|   5870 } |   5882 } | 
|   5871  |   5883  | 
|   5872  |   5884  | 
|   5873 // Emit a LoadIC call to get the value from receiver and leave it in |   5885 // Emit a LoadIC call to get the value from receiver and leave it in | 
|   5874 // dst.  The receiver register is restored after the call. |   5886 // dst.  The receiver register is restored after the call. | 
|   5875 class DeferredReferenceGetNamedValue: public DeferredCode { |   5887 class DeferredReferenceGetNamedValue: public DeferredCode { | 
|   5876  public: |   5888  public: | 
|   5877   DeferredReferenceGetNamedValue(Register dst, |   5889   DeferredReferenceGetNamedValue(Register dst, | 
| (...skipping 4589 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  10467   // Call the function from C++. |  10479   // Call the function from C++. | 
|  10468   return FUNCTION_CAST<ModuloFunction>(buffer); |  10480   return FUNCTION_CAST<ModuloFunction>(buffer); | 
|  10469 } |  10481 } | 
|  10470  |  10482  | 
|  10471 #endif |  10483 #endif | 
|  10472  |  10484  | 
|  10473  |  10485  | 
|  10474 #undef __ |  10486 #undef __ | 
|  10475  |  10487  | 
|  10476 } }  // namespace v8::internal |  10488 } }  // namespace v8::internal | 
| OLD | NEW |