~ubuntu-branches/ubuntu/saucy/libv8/saucy

« back to all changes in this revision

Viewing changes to src/ia32/code-stubs-ia32.cc

  • Committer: Package Import Robot
  • Author(s): Jérémy Lal
  • Date: 2012-04-07 16:26:13 UTC
  • mfrom: (15.1.27 sid)
  • Revision ID: package-import@ubuntu.com-20120407162613-dqo1m6w9r3fh8tst
Tags: 3.8.9.16-3
* mipsel build fixes :
  + v8_use_mips_abi_hardfloat=false, this lowers EABI requirements.
  + v8_can_use_fpu_instructions=false, detect if FPU is present.
  + set -Wno-unused-but-set-variable only on mipsel.

Show diffs side-by-side

added added

removed removed

Lines of Context:
128
128
  // Get the function from the stack.
129
129
  __ mov(ecx, Operand(esp, 1 * kPointerSize));
130
130
 
131
 
  // Setup the object header.
 
131
  // Set up the object header.
132
132
  Factory* factory = masm->isolate()->factory();
133
133
  __ mov(FieldOperand(eax, HeapObject::kMapOffset),
134
134
         factory->function_context_map());
135
135
  __ mov(FieldOperand(eax, Context::kLengthOffset),
136
136
         Immediate(Smi::FromInt(length)));
137
137
 
138
 
  // Setup the fixed slots.
 
138
  // Set up the fixed slots.
139
139
  __ Set(ebx, Immediate(0));  // Set to NULL.
140
140
  __ mov(Operand(eax, Context::SlotOffset(Context::CLOSURE_INDEX)), ecx);
141
141
  __ mov(Operand(eax, Context::SlotOffset(Context::PREVIOUS_INDEX)), esi);
179
179
  // Get the serialized scope info from the stack.
180
180
  __ mov(ebx, Operand(esp, 2 * kPointerSize));
181
181
 
182
 
  // Setup the object header.
 
182
  // Set up the object header.
183
183
  Factory* factory = masm->isolate()->factory();
184
184
  __ mov(FieldOperand(eax, HeapObject::kMapOffset),
185
185
         factory->block_context_map());
202
202
  __ mov(ecx, ContextOperand(ecx, Context::CLOSURE_INDEX));
203
203
  __ bind(&after_sentinel);
204
204
 
205
 
  // Setup the fixed slots.
 
205
  // Set up the fixed slots.
206
206
  __ mov(ContextOperand(eax, Context::CLOSURE_INDEX), ecx);
207
207
  __ mov(ContextOperand(eax, Context::PREVIOUS_INDEX), esi);
208
208
  __ mov(ContextOperand(eax, Context::EXTENSION_INDEX), ebx);
749
749
    // Exponent word in scratch, exponent part of exponent word in scratch2.
750
750
    // Zero in ecx.
751
751
    // We know the exponent is smaller than 30 (biased).  If it is less than
752
 
    // 0 (biased) then the number is smaller in magnitude than 1.0 * 2^0, ie
 
752
    // 0 (biased) then the number is smaller in magnitude than 1.0 * 2^0, i.e.
753
753
    // it rounds to zero.
754
754
    const uint32_t zero_exponent =
755
755
        (HeapNumber::kExponentBias + 0) << HeapNumber::kExponentShift;
2938
2938
 
2939
2939
 
2940
2940
void MathPowStub::Generate(MacroAssembler* masm) {
2941
 
  // Registers are used as follows:
2942
 
  // edx = base
2943
 
  // eax = exponent
2944
 
  // ecx = temporary, result
2945
 
 
2946
2941
  CpuFeatures::Scope use_sse2(SSE2);
2947
 
  Label allocate_return, call_runtime;
2948
 
 
2949
 
  // Load input parameters.
2950
 
  __ mov(edx, Operand(esp, 2 * kPointerSize));
2951
 
  __ mov(eax, Operand(esp, 1 * kPointerSize));
2952
 
 
2953
 
  // Save 1 in xmm3 - we need this several times later on.
2954
 
  __ mov(ecx, Immediate(1));
2955
 
  __ cvtsi2sd(xmm3, ecx);
2956
 
 
2957
 
  Label exponent_nonsmi;
2958
 
  Label base_nonsmi;
2959
 
  // If the exponent is a heap number go to that specific case.
2960
 
  __ JumpIfNotSmi(eax, &exponent_nonsmi);
2961
 
  __ JumpIfNotSmi(edx, &base_nonsmi);
2962
 
 
2963
 
  // Optimized version when both exponent and base are smis.
2964
 
  Label powi;
2965
 
  __ SmiUntag(edx);
2966
 
  __ cvtsi2sd(xmm0, edx);
2967
 
  __ jmp(&powi);
2968
 
  // exponent is smi and base is a heapnumber.
2969
 
  __ bind(&base_nonsmi);
2970
2942
  Factory* factory = masm->isolate()->factory();
2971
 
  __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
2972
 
         factory->heap_number_map());
2973
 
  __ j(not_equal, &call_runtime);
2974
 
 
2975
 
  __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset));
2976
 
 
2977
 
  // Optimized version of pow if exponent is a smi.
2978
 
  // xmm0 contains the base.
2979
 
  __ bind(&powi);
2980
 
  __ SmiUntag(eax);
2981
 
 
2982
 
  // Save exponent in base as we need to check if exponent is negative later.
2983
 
  // We know that base and exponent are in different registers.
2984
 
  __ mov(edx, eax);
 
2943
  const Register exponent = eax;
 
2944
  const Register base = edx;
 
2945
  const Register scratch = ecx;
 
2946
  const XMMRegister double_result = xmm3;
 
2947
  const XMMRegister double_base = xmm2;
 
2948
  const XMMRegister double_exponent = xmm1;
 
2949
  const XMMRegister double_scratch = xmm4;
 
2950
 
 
2951
  Label call_runtime, done, exponent_not_smi, int_exponent;
 
2952
 
 
2953
  // Save 1 in double_result - we need this several times later on.
 
2954
  __ mov(scratch, Immediate(1));
 
2955
  __ cvtsi2sd(double_result, scratch);
 
2956
 
 
2957
  if (exponent_type_ == ON_STACK) {
 
2958
    Label base_is_smi, unpack_exponent;
 
2959
    // The exponent and base are supplied as arguments on the stack.
 
2960
    // This can only happen if the stub is called from non-optimized code.
 
2961
    // Load input parameters from stack.
 
2962
    __ mov(base, Operand(esp, 2 * kPointerSize));
 
2963
    __ mov(exponent, Operand(esp, 1 * kPointerSize));
 
2964
 
 
2965
    __ JumpIfSmi(base, &base_is_smi, Label::kNear);
 
2966
    __ cmp(FieldOperand(base, HeapObject::kMapOffset),
 
2967
           factory->heap_number_map());
 
2968
    __ j(not_equal, &call_runtime);
 
2969
 
 
2970
    __ movdbl(double_base, FieldOperand(base, HeapNumber::kValueOffset));
 
2971
    __ jmp(&unpack_exponent, Label::kNear);
 
2972
 
 
2973
    __ bind(&base_is_smi);
 
2974
    __ SmiUntag(base);
 
2975
    __ cvtsi2sd(double_base, base);
 
2976
 
 
2977
    __ bind(&unpack_exponent);
 
2978
    __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear);
 
2979
    __ SmiUntag(exponent);
 
2980
    __ jmp(&int_exponent);
 
2981
 
 
2982
    __ bind(&exponent_not_smi);
 
2983
    __ cmp(FieldOperand(exponent, HeapObject::kMapOffset),
 
2984
           factory->heap_number_map());
 
2985
    __ j(not_equal, &call_runtime);
 
2986
    __ movdbl(double_exponent,
 
2987
              FieldOperand(exponent, HeapNumber::kValueOffset));
 
2988
  } else if (exponent_type_ == TAGGED) {
 
2989
    __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear);
 
2990
    __ SmiUntag(exponent);
 
2991
    __ jmp(&int_exponent);
 
2992
 
 
2993
    __ bind(&exponent_not_smi);
 
2994
    __ movdbl(double_exponent,
 
2995
              FieldOperand(exponent, HeapNumber::kValueOffset));
 
2996
  }
 
2997
 
 
2998
  if (exponent_type_ != INTEGER) {
 
2999
    Label fast_power;
 
3000
    // Detect integer exponents stored as double.
 
3001
    __ cvttsd2si(exponent, Operand(double_exponent));
 
3002
    // Skip to runtime if possibly NaN (indicated by the indefinite integer).
 
3003
    __ cmp(exponent, Immediate(0x80000000u));
 
3004
    __ j(equal, &call_runtime);
 
3005
    __ cvtsi2sd(double_scratch, exponent);
 
3006
    // Already ruled out NaNs for exponent.
 
3007
    __ ucomisd(double_exponent, double_scratch);
 
3008
    __ j(equal, &int_exponent);
 
3009
 
 
3010
    if (exponent_type_ == ON_STACK) {
 
3011
      // Detect square root case.  Crankshaft detects constant +/-0.5 at
 
3012
      // compile time and uses DoMathPowHalf instead.  We then skip this check
 
3013
      // for non-constant cases of +/-0.5 as these hardly occur.
 
3014
      Label continue_sqrt, continue_rsqrt, not_plus_half;
 
3015
      // Test for 0.5.
 
3016
      // Load double_scratch with 0.5.
 
3017
      __ mov(scratch, Immediate(0x3F000000u));
 
3018
      __ movd(double_scratch, scratch);
 
3019
      __ cvtss2sd(double_scratch, double_scratch);
 
3020
      // Already ruled out NaNs for exponent.
 
3021
      __ ucomisd(double_scratch, double_exponent);
 
3022
      __ j(not_equal, &not_plus_half, Label::kNear);
 
3023
 
 
3024
      // Calculates square root of base.  Check for the special case of
 
3025
      // Math.pow(-Infinity, 0.5) == Infinity (ECMA spec, 15.8.2.13).
 
3026
      // According to IEEE-754, single-precision -Infinity has the highest
 
3027
      // 9 bits set and the lowest 23 bits cleared.
 
3028
      __ mov(scratch, 0xFF800000u);
 
3029
      __ movd(double_scratch, scratch);
 
3030
      __ cvtss2sd(double_scratch, double_scratch);
 
3031
      __ ucomisd(double_base, double_scratch);
 
3032
      // Comparing -Infinity with NaN results in "unordered", which sets the
 
3033
      // zero flag as if both were equal.  However, it also sets the carry flag.
 
3034
      __ j(not_equal, &continue_sqrt, Label::kNear);
 
3035
      __ j(carry, &continue_sqrt, Label::kNear);
 
3036
 
 
3037
      // Set result to Infinity in the special case.
 
3038
      __ xorps(double_result, double_result);
 
3039
      __ subsd(double_result, double_scratch);
 
3040
      __ jmp(&done);
 
3041
 
 
3042
      __ bind(&continue_sqrt);
 
3043
      // sqrtsd returns -0 when input is -0.  ECMA spec requires +0.
 
3044
      __ xorps(double_scratch, double_scratch);
 
3045
      __ addsd(double_scratch, double_base);  // Convert -0 to +0.
 
3046
      __ sqrtsd(double_result, double_scratch);
 
3047
      __ jmp(&done);
 
3048
 
 
3049
      // Test for -0.5.
 
3050
      __ bind(&not_plus_half);
 
3051
      // Load double_exponent with -0.5 by substracting 1.
 
3052
      __ subsd(double_scratch, double_result);
 
3053
      // Already ruled out NaNs for exponent.
 
3054
      __ ucomisd(double_scratch, double_exponent);
 
3055
      __ j(not_equal, &fast_power, Label::kNear);
 
3056
 
 
3057
      // Calculates reciprocal of square root of base.  Check for the special
 
3058
      // case of Math.pow(-Infinity, -0.5) == 0 (ECMA spec, 15.8.2.13).
 
3059
      // According to IEEE-754, single-precision -Infinity has the highest
 
3060
      // 9 bits set and the lowest 23 bits cleared.
 
3061
      __ mov(scratch, 0xFF800000u);
 
3062
      __ movd(double_scratch, scratch);
 
3063
      __ cvtss2sd(double_scratch, double_scratch);
 
3064
      __ ucomisd(double_base, double_scratch);
 
3065
      // Comparing -Infinity with NaN results in "unordered", which sets the
 
3066
      // zero flag as if both were equal.  However, it also sets the carry flag.
 
3067
      __ j(not_equal, &continue_rsqrt, Label::kNear);
 
3068
      __ j(carry, &continue_rsqrt, Label::kNear);
 
3069
 
 
3070
      // Set result to 0 in the special case.
 
3071
      __ xorps(double_result, double_result);
 
3072
      __ jmp(&done);
 
3073
 
 
3074
      __ bind(&continue_rsqrt);
 
3075
      // sqrtsd returns -0 when input is -0.  ECMA spec requires +0.
 
3076
      __ xorps(double_exponent, double_exponent);
 
3077
      __ addsd(double_exponent, double_base);  // Convert -0 to +0.
 
3078
      __ sqrtsd(double_exponent, double_exponent);
 
3079
      __ divsd(double_result, double_exponent);
 
3080
      __ jmp(&done);
 
3081
    }
 
3082
 
 
3083
    // Using FPU instructions to calculate power.
 
3084
    Label fast_power_failed;
 
3085
    __ bind(&fast_power);
 
3086
    __ fnclex();  // Clear flags to catch exceptions later.
 
3087
    // Transfer (B)ase and (E)xponent onto the FPU register stack.
 
3088
    __ sub(esp, Immediate(kDoubleSize));
 
3089
    __ movdbl(Operand(esp, 0), double_exponent);
 
3090
    __ fld_d(Operand(esp, 0));  // E
 
3091
    __ movdbl(Operand(esp, 0), double_base);
 
3092
    __ fld_d(Operand(esp, 0));  // B, E
 
3093
 
 
3094
    // Exponent is in st(1) and base is in st(0)
 
3095
    // B ^ E = (2^(E * log2(B)) - 1) + 1 = (2^X - 1) + 1 for X = E * log2(B)
 
3096
    // FYL2X calculates st(1) * log2(st(0))
 
3097
    __ fyl2x();    // X
 
3098
    __ fld(0);     // X, X
 
3099
    __ frndint();  // rnd(X), X
 
3100
    __ fsub(1);    // rnd(X), X-rnd(X)
 
3101
    __ fxch(1);    // X - rnd(X), rnd(X)
 
3102
    // F2XM1 calculates 2^st(0) - 1 for -1 < st(0) < 1
 
3103
    __ f2xm1();    // 2^(X-rnd(X)) - 1, rnd(X)
 
3104
    __ fld1();     // 1, 2^(X-rnd(X)) - 1, rnd(X)
 
3105
    __ faddp(1);   // 1, 2^(X-rnd(X)), rnd(X)
 
3106
    // FSCALE calculates st(0) * 2^st(1)
 
3107
    __ fscale();   // 2^X, rnd(X)
 
3108
    __ fstp(1);
 
3109
    // Bail out to runtime in case of exceptions in the status word.
 
3110
    __ fnstsw_ax();
 
3111
    __ test_b(eax, 0x5F);  // We check for all but precision exception.
 
3112
    __ j(not_zero, &fast_power_failed, Label::kNear);
 
3113
    __ fstp_d(Operand(esp, 0));
 
3114
    __ movdbl(double_result, Operand(esp, 0));
 
3115
    __ add(esp, Immediate(kDoubleSize));
 
3116
    __ jmp(&done);
 
3117
 
 
3118
    __ bind(&fast_power_failed);
 
3119
    __ fninit();
 
3120
    __ add(esp, Immediate(kDoubleSize));
 
3121
    __ jmp(&call_runtime);
 
3122
  }
 
3123
 
 
3124
  // Calculate power with integer exponent.
 
3125
  __ bind(&int_exponent);
 
3126
  const XMMRegister double_scratch2 = double_exponent;
 
3127
  __ mov(scratch, exponent);  // Back up exponent.
 
3128
  __ movsd(double_scratch, double_base);  // Back up base.
 
3129
  __ movsd(double_scratch2, double_result);  // Load double_exponent with 1.
2985
3130
 
2986
3131
  // Get absolute value of exponent.
2987
 
  Label no_neg;
2988
 
  __ cmp(eax, 0);
2989
 
  __ j(greater_equal, &no_neg, Label::kNear);
2990
 
  __ neg(eax);
 
3132
  Label no_neg, while_true, no_multiply;
 
3133
  __ test(scratch, scratch);
 
3134
  __ j(positive, &no_neg, Label::kNear);
 
3135
  __ neg(scratch);
2991
3136
  __ bind(&no_neg);
2992
3137
 
2993
 
  // Load xmm1 with 1.
2994
 
  __ movsd(xmm1, xmm3);
2995
 
  Label while_true;
2996
 
  Label no_multiply;
2997
 
 
2998
3138
  __ bind(&while_true);
2999
 
  __ shr(eax, 1);
 
3139
  __ shr(scratch, 1);
3000
3140
  __ j(not_carry, &no_multiply, Label::kNear);
3001
 
  __ mulsd(xmm1, xmm0);
 
3141
  __ mulsd(double_result, double_scratch);
3002
3142
  __ bind(&no_multiply);
3003
 
  __ mulsd(xmm0, xmm0);
 
3143
 
 
3144
  __ mulsd(double_scratch, double_scratch);
3004
3145
  __ j(not_zero, &while_true);
3005
3146
 
3006
 
  // base has the original value of the exponent - if the exponent  is
3007
 
  // negative return 1/result.
3008
 
  __ test(edx, edx);
3009
 
  __ j(positive, &allocate_return);
3010
 
  // Special case if xmm1 has reached infinity.
3011
 
  __ mov(ecx, Immediate(0x7FB00000));
3012
 
  __ movd(xmm0, ecx);
3013
 
  __ cvtss2sd(xmm0, xmm0);
3014
 
  __ ucomisd(xmm0, xmm1);
3015
 
  __ j(equal, &call_runtime);
3016
 
  __ divsd(xmm3, xmm1);
3017
 
  __ movsd(xmm1, xmm3);
3018
 
  __ jmp(&allocate_return);
3019
 
 
3020
 
  // exponent (or both) is a heapnumber - no matter what we should now work
3021
 
  // on doubles.
3022
 
  __ bind(&exponent_nonsmi);
3023
 
  __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
3024
 
         factory->heap_number_map());
3025
 
  __ j(not_equal, &call_runtime);
3026
 
  __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
3027
 
  // Test if exponent is nan.
3028
 
  __ ucomisd(xmm1, xmm1);
3029
 
  __ j(parity_even, &call_runtime);
3030
 
 
3031
 
  Label base_not_smi;
3032
 
  Label handle_special_cases;
3033
 
  __ JumpIfNotSmi(edx, &base_not_smi, Label::kNear);
3034
 
  __ SmiUntag(edx);
3035
 
  __ cvtsi2sd(xmm0, edx);
3036
 
  __ jmp(&handle_special_cases, Label::kNear);
3037
 
 
3038
 
  __ bind(&base_not_smi);
3039
 
  __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
3040
 
         factory->heap_number_map());
3041
 
  __ j(not_equal, &call_runtime);
3042
 
  __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset));
3043
 
  __ and_(ecx, HeapNumber::kExponentMask);
3044
 
  __ cmp(ecx, Immediate(HeapNumber::kExponentMask));
3045
 
  // base is NaN or +/-Infinity
3046
 
  __ j(greater_equal, &call_runtime);
3047
 
  __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset));
3048
 
 
3049
 
  // base is in xmm0 and exponent is in xmm1.
3050
 
  __ bind(&handle_special_cases);
3051
 
  Label not_minus_half;
3052
 
  // Test for -0.5.
3053
 
  // Load xmm2 with -0.5.
3054
 
  __ mov(ecx, Immediate(0xBF000000));
3055
 
  __ movd(xmm2, ecx);
3056
 
  __ cvtss2sd(xmm2, xmm2);
3057
 
  // xmm2 now has -0.5.
3058
 
  __ ucomisd(xmm2, xmm1);
3059
 
  __ j(not_equal, &not_minus_half, Label::kNear);
3060
 
 
3061
 
  // Calculates reciprocal of square root.
3062
 
  // sqrtsd returns -0 when input is -0.  ECMA spec requires +0.
3063
 
  __ xorps(xmm1, xmm1);
3064
 
  __ addsd(xmm1, xmm0);
3065
 
  __ sqrtsd(xmm1, xmm1);
3066
 
  __ divsd(xmm3, xmm1);
3067
 
  __ movsd(xmm1, xmm3);
3068
 
  __ jmp(&allocate_return);
3069
 
 
3070
 
  // Test for 0.5.
3071
 
  __ bind(&not_minus_half);
3072
 
  // Load xmm2 with 0.5.
3073
 
  // Since xmm3 is 1 and xmm2 is -0.5 this is simply xmm2 + xmm3.
3074
 
  __ addsd(xmm2, xmm3);
3075
 
  // xmm2 now has 0.5.
3076
 
  __ ucomisd(xmm2, xmm1);
3077
 
  __ j(not_equal, &call_runtime);
3078
 
  // Calculates square root.
3079
 
  // sqrtsd returns -0 when input is -0.  ECMA spec requires +0.
3080
 
  __ xorps(xmm1, xmm1);
3081
 
  __ addsd(xmm1, xmm0);
3082
 
  __ sqrtsd(xmm1, xmm1);
3083
 
 
3084
 
  __ bind(&allocate_return);
3085
 
  __ AllocateHeapNumber(ecx, eax, edx, &call_runtime);
3086
 
  __ movdbl(FieldOperand(ecx, HeapNumber::kValueOffset), xmm1);
3087
 
  __ mov(eax, ecx);
3088
 
  __ ret(2 * kPointerSize);
3089
 
 
3090
 
  __ bind(&call_runtime);
3091
 
  __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1);
 
3147
  // scratch has the original value of the exponent - if the exponent is
 
3148
  // negative, return 1/result.
 
3149
  __ test(exponent, exponent);
 
3150
  __ j(positive, &done);
 
3151
  __ divsd(double_scratch2, double_result);
 
3152
  __ movsd(double_result, double_scratch2);
 
3153
  // Test whether result is zero.  Bail out to check for subnormal result.
 
3154
  // Due to subnormals, x^-y == (1/x)^y does not hold in all cases.
 
3155
  __ xorps(double_scratch2, double_scratch2);
 
3156
  __ ucomisd(double_scratch2, double_result);  // Result cannot be NaN.
 
3157
  // double_exponent aliased as double_scratch2 has already been overwritten
 
3158
  // and may not have contained the exponent value in the first place when the
 
3159
  // exponent is a smi.  We reset it with exponent value before bailing out.
 
3160
  __ j(not_equal, &done);
 
3161
  __ cvtsi2sd(double_exponent, exponent);
 
3162
 
 
3163
  // Returning or bailing out.
 
3164
  Counters* counters = masm->isolate()->counters();
 
3165
  if (exponent_type_ == ON_STACK) {
 
3166
    // The arguments are still on the stack.
 
3167
    __ bind(&call_runtime);
 
3168
    __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1);
 
3169
 
 
3170
    // The stub is called from non-optimized code, which expects the result
 
3171
    // as heap number in exponent.
 
3172
    __ bind(&done);
 
3173
    __ AllocateHeapNumber(eax, scratch, base, &call_runtime);
 
3174
    __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), double_result);
 
3175
    __ IncrementCounter(counters->math_pow(), 1);
 
3176
    __ ret(2 * kPointerSize);
 
3177
  } else {
 
3178
    __ bind(&call_runtime);
 
3179
    {
 
3180
      AllowExternalCallThatCantCauseGC scope(masm);
 
3181
      __ PrepareCallCFunction(4, scratch);
 
3182
      __ movdbl(Operand(esp, 0 * kDoubleSize), double_base);
 
3183
      __ movdbl(Operand(esp, 1 * kDoubleSize), double_exponent);
 
3184
      __ CallCFunction(
 
3185
          ExternalReference::power_double_double_function(masm->isolate()), 4);
 
3186
    }
 
3187
    // Return value is in st(0) on ia32.
 
3188
    // Store it into the (fixed) result register.
 
3189
    __ sub(esp, Immediate(kDoubleSize));
 
3190
    __ fstp_d(Operand(esp, 0));
 
3191
    __ movdbl(double_result, Operand(esp, 0));
 
3192
    __ add(esp, Immediate(kDoubleSize));
 
3193
 
 
3194
    __ bind(&done);
 
3195
    __ IncrementCounter(counters->math_pow(), 1);
 
3196
    __ ret(0);
 
3197
  }
3092
3198
}
3093
3199
 
3094
3200
 
3273
3379
    __ mov(FieldOperand(eax, i), edx);
3274
3380
  }
3275
3381
 
3276
 
  // Setup the callee in-object property.
 
3382
  // Set up the callee in-object property.
3277
3383
  STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
3278
3384
  __ mov(edx, Operand(esp, 4 * kPointerSize));
3279
3385
  __ mov(FieldOperand(eax, JSObject::kHeaderSize +
3286
3392
                      Heap::kArgumentsLengthIndex * kPointerSize),
3287
3393
         ecx);
3288
3394
 
3289
 
  // Setup the elements pointer in the allocated arguments object.
 
3395
  // Set up the elements pointer in the allocated arguments object.
3290
3396
  // If we allocated a parameter map, edi will point there, otherwise to the
3291
3397
  // backing store.
3292
3398
  __ lea(edi, Operand(eax, Heap::kArgumentsObjectSize));
3465
3571
  // Get the parameters pointer from the stack.
3466
3572
  __ mov(edx, Operand(esp, 2 * kPointerSize));
3467
3573
 
3468
 
  // Setup the elements pointer in the allocated arguments object and
 
3574
  // Set up the elements pointer in the allocated arguments object and
3469
3575
  // initialize the header in the elements fixed array.
3470
3576
  __ lea(edi, Operand(eax, Heap::kArgumentsObjectSizeStrict));
3471
3577
  __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi);
3617
3723
               kShortExternalStringMask);
3618
3724
  STATIC_ASSERT((kStringTag | kSeqStringTag | kTwoByteStringTag) == 0);
3619
3725
  __ j(zero, &seq_two_byte_string, Label::kNear);
3620
 
  // Any other flat string must be a flat ascii string.  None of the following
 
3726
  // Any other flat string must be a flat ASCII string.  None of the following
3621
3727
  // string type tests will succeed if subject is not a string or a short
3622
3728
  // external string.
3623
3729
  __ and_(ebx, Immediate(kIsNotStringMask |
3666
3772
            kStringRepresentationMask | kStringEncodingMask);
3667
3773
  STATIC_ASSERT((kSeqStringTag | kTwoByteStringTag) == 0);
3668
3774
  __ j(zero, &seq_two_byte_string, Label::kNear);
3669
 
  // Any other flat string must be sequential ascii or external.
 
3775
  // Any other flat string must be sequential ASCII or external.
3670
3776
  __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset),
3671
3777
            kStringRepresentationMask);
3672
3778
  __ j(not_zero, &external_string);
3673
3779
 
3674
3780
  __ bind(&seq_ascii_string);
3675
 
  // eax: subject string (flat ascii)
 
3781
  // eax: subject string (flat ASCII)
3676
3782
  // ecx: RegExp data (FixedArray)
3677
3783
  __ mov(edx, FieldOperand(ecx, JSRegExp::kDataAsciiCodeOffset));
3678
 
  __ Set(ecx, Immediate(1));  // Type is ascii.
 
3784
  __ Set(ecx, Immediate(1));  // Type is ASCII.
3679
3785
  __ jmp(&check_code, Label::kNear);
3680
3786
 
3681
3787
  __ bind(&seq_two_byte_string);
3692
3798
 
3693
3799
  // eax: subject string
3694
3800
  // edx: code
3695
 
  // ecx: encoding of subject string (1 if ascii, 0 if two_byte);
 
3801
  // ecx: encoding of subject string (1 if ASCII, 0 if two_byte);
3696
3802
  // Load used arguments before starting to push arguments for call to native
3697
3803
  // RegExp code to avoid handling changing stack height.
3698
3804
  __ mov(ebx, Operand(esp, kPreviousIndexOffset));
3701
3807
  // eax: subject string
3702
3808
  // ebx: previous index
3703
3809
  // edx: code
3704
 
  // ecx: encoding of subject string (1 if ascii 0 if two_byte);
 
3810
  // ecx: encoding of subject string (1 if ASCII 0 if two_byte);
3705
3811
  // All checks done. Now push arguments for native regexp code.
3706
3812
  Counters* counters = masm->isolate()->counters();
3707
3813
  __ IncrementCounter(counters->regexp_entry_native(), 1);
3741
3847
  // esi: original subject string
3742
3848
  // eax: underlying subject string
3743
3849
  // ebx: previous index
3744
 
  // ecx: encoding of subject string (1 if ascii 0 if two_byte);
 
3850
  // ecx: encoding of subject string (1 if ASCII 0 if two_byte);
3745
3851
  // edx: code
3746
3852
  // Argument 4: End of string data
3747
3853
  // Argument 3: Start of string data
4369
4475
  __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx,
4370
4476
                                         &check_unequal_objects);
4371
4477
 
4372
 
  // Inline comparison of ascii strings.
 
4478
  // Inline comparison of ASCII strings.
4373
4479
  if (cc_ == equal) {
4374
4480
    StringCompareStub::GenerateFlatAsciiStringEquals(masm,
4375
4481
                                                     edx,
4844
4950
  Label invoke, handler_entry, exit;
4845
4951
  Label not_outermost_js, not_outermost_js_2;
4846
4952
 
4847
 
  // Setup frame.
 
4953
  // Set up frame.
4848
4954
  __ push(ebp);
4849
4955
  __ mov(ebp, esp);
4850
4956
 
5322
5428
  STATIC_ASSERT(kSmiTag == 0);
5323
5429
  STATIC_ASSERT(kSmiTagSize == 1);
5324
5430
  STATIC_ASSERT(kSmiShiftSize == 0);
5325
 
  // At this point code register contains smi tagged ascii char code.
 
5431
  // At this point code register contains smi tagged ASCII char code.
5326
5432
  __ mov(result_, FieldOperand(result_,
5327
5433
                               code_, times_half_pointer_size,
5328
5434
                               FixedArray::kHeaderSize));
5369
5475
 
5370
5476
 
5371
5477
void StringAddStub::Generate(MacroAssembler* masm) {
5372
 
  Label string_add_runtime, call_builtin;
 
5478
  Label call_runtime, call_builtin;
5373
5479
  Builtins::JavaScript builtin_id = Builtins::ADD;
5374
5480
 
5375
5481
  // Load the two arguments.
5378
5484
 
5379
5485
  // Make sure that both arguments are strings if not known in advance.
5380
5486
  if (flags_ == NO_STRING_ADD_FLAGS) {
5381
 
    __ JumpIfSmi(eax, &string_add_runtime);
 
5487
    __ JumpIfSmi(eax, &call_runtime);
5382
5488
    __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ebx);
5383
 
    __ j(above_equal, &string_add_runtime);
 
5489
    __ j(above_equal, &call_runtime);
5384
5490
 
5385
5491
    // First argument is a a string, test second.
5386
 
    __ JumpIfSmi(edx, &string_add_runtime);
 
5492
    __ JumpIfSmi(edx, &call_runtime);
5387
5493
    __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, ebx);
5388
 
    __ j(above_equal, &string_add_runtime);
 
5494
    __ j(above_equal, &call_runtime);
5389
5495
  } else {
5390
5496
    // Here at least one of the arguments is definitely a string.
5391
5497
    // We convert the one that is not known to be a string.
5436
5542
  __ add(ebx, ecx);
5437
5543
  STATIC_ASSERT(Smi::kMaxValue == String::kMaxLength);
5438
5544
  // Handle exceptionally long strings in the runtime system.
5439
 
  __ j(overflow, &string_add_runtime);
 
5545
  __ j(overflow, &call_runtime);
5440
5546
  // Use the symbol table when adding two one character strings, as it
5441
5547
  // helps later optimizations to return a symbol here.
5442
5548
  __ cmp(ebx, Immediate(Smi::FromInt(2)));
5443
5549
  __ j(not_equal, &longer_than_two);
5444
5550
 
5445
 
  // Check that both strings are non-external ascii strings.
5446
 
  __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx,
5447
 
                                         &string_add_runtime);
 
5551
  // Check that both strings are non-external ASCII strings.
 
5552
  __ JumpIfNotBothSequentialAsciiStrings(eax, edx, ebx, ecx, &call_runtime);
5448
5553
 
5449
5554
  // Get the two characters forming the new string.
5450
5555
  __ movzx_b(ebx, FieldOperand(eax, SeqAsciiString::kHeaderSize));
5469
5574
  __ movzx_b(ecx, FieldOperand(edx, SeqAsciiString::kHeaderSize));
5470
5575
  __ bind(&make_two_character_string_no_reload);
5471
5576
  __ IncrementCounter(counters->string_add_make_two_char(), 1);
5472
 
  __ AllocateAsciiString(eax,  // Result.
5473
 
                         2,    // Length.
5474
 
                         edi,  // Scratch 1.
5475
 
                         edx,  // Scratch 2.
5476
 
                         &string_add_runtime);
 
5577
  __ AllocateAsciiString(eax, 2, edi, edx, &call_runtime);
5477
5578
  // Pack both characters in ebx.
5478
5579
  __ shl(ecx, kBitsPerByte);
5479
5580
  __ or_(ebx, ecx);
5484
5585
 
5485
5586
  __ bind(&longer_than_two);
5486
5587
  // Check if resulting string will be flat.
5487
 
  __ cmp(ebx, Immediate(Smi::FromInt(String::kMinNonFlatLength)));
 
5588
  __ cmp(ebx, Immediate(Smi::FromInt(ConsString::kMinLength)));
5488
5589
  __ j(below, &string_add_flat_result);
5489
5590
 
5490
5591
  // If result is not supposed to be flat allocate a cons string object. If both
5491
 
  // strings are ascii the result is an ascii cons string.
 
5592
  // strings are ASCII the result is an ASCII cons string.
5492
5593
  Label non_ascii, allocated, ascii_data;
5493
5594
  __ mov(edi, FieldOperand(eax, HeapObject::kMapOffset));
5494
5595
  __ movzx_b(ecx, FieldOperand(edi, Map::kInstanceTypeOffset));
5500
5601
  __ test(ecx, Immediate(kStringEncodingMask));
5501
5602
  __ j(zero, &non_ascii);
5502
5603
  __ bind(&ascii_data);
5503
 
  // Allocate an acsii cons string.
5504
 
  __ AllocateAsciiConsString(ecx, edi, no_reg, &string_add_runtime);
 
5604
  // Allocate an ASCII cons string.
 
5605
  __ AllocateAsciiConsString(ecx, edi, no_reg, &call_runtime);
5505
5606
  __ bind(&allocated);
5506
5607
  // Fill the fields of the cons string.
5507
5608
  if (FLAG_debug_code) __ AbortIfNotSmi(ebx);
5515
5616
  __ ret(2 * kPointerSize);
5516
5617
  __ bind(&non_ascii);
5517
5618
  // At least one of the strings is two-byte. Check whether it happens
5518
 
  // to contain only ascii characters.
 
5619
  // to contain only ASCII characters.
5519
5620
  // ecx: first instance type AND second instance type.
5520
5621
  // edi: second instance type.
5521
5622
  __ test(ecx, Immediate(kAsciiDataHintMask));
5528
5629
  __ cmp(edi, kAsciiStringTag | kAsciiDataHintTag);
5529
5630
  __ j(equal, &ascii_data);
5530
5631
  // Allocate a two byte cons string.
5531
 
  __ AllocateTwoByteConsString(ecx, edi, no_reg, &string_add_runtime);
 
5632
  __ AllocateTwoByteConsString(ecx, edi, no_reg, &call_runtime);
5532
5633
  __ jmp(&allocated);
5533
5634
 
5534
 
  // Handle creating a flat result. First check that both strings are not
5535
 
  // external strings.
 
5635
  // We cannot encounter sliced strings or cons strings here since:
 
5636
  STATIC_ASSERT(SlicedString::kMinLength >= ConsString::kMinLength);
 
5637
  // Handle creating a flat result from either external or sequential strings.
 
5638
  // Locate the first characters' locations.
5536
5639
  // eax: first string
5537
5640
  // ebx: length of resulting flat string as a smi
5538
5641
  // edx: second string
 
5642
  Label first_prepared, second_prepared;
 
5643
  Label first_is_sequential, second_is_sequential;
5539
5644
  __ bind(&string_add_flat_result);
5540
5645
  __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
5541
5646
  __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
5542
 
  __ and_(ecx, kStringRepresentationMask);
5543
 
  __ cmp(ecx, kExternalStringTag);
5544
 
  __ j(equal, &string_add_runtime);
5545
 
  __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
5546
 
  __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
5547
 
  __ and_(ecx, kStringRepresentationMask);
5548
 
  __ cmp(ecx, kExternalStringTag);
5549
 
  __ j(equal, &string_add_runtime);
5550
 
  // We cannot encounter sliced strings here since:
5551
 
  STATIC_ASSERT(SlicedString::kMinLength >= String::kMinNonFlatLength);
5552
 
  // Now check if both strings are ascii strings.
5553
 
  // eax: first string
5554
 
  // ebx: length of resulting flat string as a smi
5555
 
  // edx: second string
5556
 
  Label non_ascii_string_add_flat_result;
5557
 
  STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
5558
 
  STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
5559
 
  __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
5560
 
  __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kStringEncodingMask);
 
5647
  // ecx: instance type of first string
 
5648
  STATIC_ASSERT(kSeqStringTag == 0);
 
5649
  __ test_b(ecx, kStringRepresentationMask);
 
5650
  __ j(zero, &first_is_sequential, Label::kNear);
 
5651
  // Rule out short external string and load string resource.
 
5652
  STATIC_ASSERT(kShortExternalStringTag != 0);
 
5653
  __ test_b(ecx, kShortExternalStringMask);
 
5654
  __ j(not_zero, &call_runtime);
 
5655
  __ mov(eax, FieldOperand(eax, ExternalString::kResourceDataOffset));
 
5656
  STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize);
 
5657
  __ jmp(&first_prepared, Label::kNear);
 
5658
  __ bind(&first_is_sequential);
 
5659
  __ add(eax, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
 
5660
  __ bind(&first_prepared);
 
5661
 
 
5662
  __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
 
5663
  __ movzx_b(edi, FieldOperand(edi, Map::kInstanceTypeOffset));
 
5664
  // Check whether both strings have same encoding.
 
5665
  // edi: instance type of second string
 
5666
  __ xor_(ecx, edi);
 
5667
  __ test_b(ecx, kStringEncodingMask);
 
5668
  __ j(not_zero, &call_runtime);
 
5669
  STATIC_ASSERT(kSeqStringTag == 0);
 
5670
  __ test_b(edi, kStringRepresentationMask);
 
5671
  __ j(zero, &second_is_sequential, Label::kNear);
 
5672
  // Rule out short external string and load string resource.
 
5673
  STATIC_ASSERT(kShortExternalStringTag != 0);
 
5674
  __ test_b(edi, kShortExternalStringMask);
 
5675
  __ j(not_zero, &call_runtime);
 
5676
  __ mov(edx, FieldOperand(edx, ExternalString::kResourceDataOffset));
 
5677
  STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize);
 
5678
  __ jmp(&second_prepared, Label::kNear);
 
5679
  __ bind(&second_is_sequential);
 
5680
  __ add(edx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
 
5681
  __ bind(&second_prepared);
 
5682
 
 
5683
  // Push the addresses of both strings' first characters onto the stack.
 
5684
  __ push(edx);
 
5685
  __ push(eax);
 
5686
 
 
5687
  Label non_ascii_string_add_flat_result, call_runtime_drop_two;
 
5688
  // edi: instance type of second string
 
5689
  // First string and second string have the same encoding.
 
5690
  STATIC_ASSERT(kTwoByteStringTag == 0);
 
5691
  __ test_b(edi, kStringEncodingMask);
5561
5692
  __ j(zero, &non_ascii_string_add_flat_result);
5562
 
  __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
5563
 
  __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kStringEncodingMask);
5564
 
  __ j(zero, &string_add_runtime);
5565
5693
 
5566
 
  // Both strings are ascii strings.  As they are short they are both flat.
 
5694
  // Both strings are ASCII strings.
5567
5695
  // ebx: length of resulting flat string as a smi
5568
5696
  __ SmiUntag(ebx);
5569
 
  __ AllocateAsciiString(eax, ebx, ecx, edx, edi, &string_add_runtime);
 
5697
  __ AllocateAsciiString(eax, ebx, ecx, edx, edi, &call_runtime_drop_two);
5570
5698
  // eax: result string
5571
5699
  __ mov(ecx, eax);
5572
5700
  // Locate first character of result.
5573
5701
  __ add(ecx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
5574
 
  // Load first argument and locate first character.
5575
 
  __ mov(edx, Operand(esp, 2 * kPointerSize));
 
5702
  // Load first argument's length and first character location.  Account for
 
5703
  // values currently on the stack when fetching arguments from it.
 
5704
  __ mov(edx, Operand(esp, 4 * kPointerSize));
5576
5705
  __ mov(edi, FieldOperand(edx, String::kLengthOffset));
5577
5706
  __ SmiUntag(edi);
5578
 
  __ add(edx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
 
5707
  __ pop(edx);
5579
5708
  // eax: result string
5580
5709
  // ecx: first character of result
5581
5710
  // edx: first char of first argument
5582
5711
  // edi: length of first argument
5583
5712
  StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true);
5584
 
  // Load second argument and locate first character.
5585
 
  __ mov(edx, Operand(esp, 1 * kPointerSize));
 
5713
  // Load second argument's length and first character location.  Account for
 
5714
  // values currently on the stack when fetching arguments from it.
 
5715
  __ mov(edx, Operand(esp, 2 * kPointerSize));
5586
5716
  __ mov(edi, FieldOperand(edx, String::kLengthOffset));
5587
5717
  __ SmiUntag(edi);
5588
 
  __ add(edx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
 
5718
  __ pop(edx);
5589
5719
  // eax: result string
5590
5720
  // ecx: next character of result
5591
5721
  // edx: first char of second argument
5599
5729
  // ebx: length of resulting flat string as a smi
5600
5730
  // edx: second string
5601
5731
  __ bind(&non_ascii_string_add_flat_result);
5602
 
  __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
5603
 
  __ test_b(FieldOperand(ecx, Map::kInstanceTypeOffset), kStringEncodingMask);
5604
 
  __ j(not_zero, &string_add_runtime);
5605
 
  // Both strings are two byte strings. As they are short they are both
5606
 
  // flat.
 
5732
  // Both strings are two byte strings.
5607
5733
  __ SmiUntag(ebx);
5608
 
  __ AllocateTwoByteString(eax, ebx, ecx, edx, edi, &string_add_runtime);
 
5734
  __ AllocateTwoByteString(eax, ebx, ecx, edx, edi, &call_runtime_drop_two);
5609
5735
  // eax: result string
5610
5736
  __ mov(ecx, eax);
5611
5737
  // Locate first character of result.
5612
 
  __ add(ecx,
5613
 
         Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
5614
 
  // Load first argument and locate first character.
5615
 
  __ mov(edx, Operand(esp, 2 * kPointerSize));
 
5738
  __ add(ecx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
 
5739
  // Load second argument's length and first character location.  Account for
 
5740
  // values currently on the stack when fetching arguments from it.
 
5741
  __ mov(edx, Operand(esp, 4 * kPointerSize));
5616
5742
  __ mov(edi, FieldOperand(edx, String::kLengthOffset));
5617
5743
  __ SmiUntag(edi);
5618
 
  __ add(edx,
5619
 
         Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
 
5744
  __ pop(edx);
5620
5745
  // eax: result string
5621
5746
  // ecx: first character of result
5622
5747
  // edx: first char of first argument
5623
5748
  // edi: length of first argument
5624
5749
  StringHelper::GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false);
5625
 
  // Load second argument and locate first character.
5626
 
  __ mov(edx, Operand(esp, 1 * kPointerSize));
 
5750
  // Load second argument's length and first character location.  Account for
 
5751
  // values currently on the stack when fetching arguments from it.
 
5752
  __ mov(edx, Operand(esp, 2 * kPointerSize));
5627
5753
  __ mov(edi, FieldOperand(edx, String::kLengthOffset));
5628
5754
  __ SmiUntag(edi);
5629
 
  __ add(edx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
 
5755
  __ pop(edx);
5630
5756
  // eax: result string
5631
5757
  // ecx: next character of result
5632
5758
  // edx: first char of second argument
5635
5761
  __ IncrementCounter(counters->string_add_native(), 1);
5636
5762
  __ ret(2 * kPointerSize);
5637
5763
 
 
5764
  // Recover stack pointer before jumping to runtime.
 
5765
  __ bind(&call_runtime_drop_two);
 
5766
  __ Drop(2);
5638
5767
  // Just jump to runtime to add the two strings.
5639
 
  __ bind(&string_add_runtime);
 
5768
  __ bind(&call_runtime);
5640
5769
  __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
5641
5770
 
5642
5771
  if (call_builtin.is_linked()) {
5872
6001
    __ push(mask);
5873
6002
    Register temp = mask;
5874
6003
 
5875
 
    // Check that the candidate is a non-external ascii string.
 
6004
    // Check that the candidate is a non-external ASCII string.
5876
6005
    __ mov(temp, FieldOperand(candidate, HeapObject::kMapOffset));
5877
6006
    __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
5878
6007
    __ JumpIfInstanceTypeIsNotSequentialAscii(
5905
6034
                                    Register hash,
5906
6035
                                    Register character,
5907
6036
                                    Register scratch) {
5908
 
  // hash = character + (character << 10);
5909
 
  __ mov(hash, character);
5910
 
  __ shl(hash, 10);
5911
 
  __ add(hash, character);
 
6037
  // hash = (seed + character) + ((seed + character) << 10);
 
6038
  if (Serializer::enabled()) {
 
6039
    ExternalReference roots_array_start =
 
6040
        ExternalReference::roots_array_start(masm->isolate());
 
6041
    __ mov(scratch, Immediate(Heap::kHashSeedRootIndex));
 
6042
    __ mov(scratch, Operand::StaticArray(scratch,
 
6043
                                         times_pointer_size,
 
6044
                                         roots_array_start));
 
6045
    __ SmiUntag(scratch);
 
6046
    __ add(scratch, character);
 
6047
    __ mov(hash, scratch);
 
6048
    __ shl(scratch, 10);
 
6049
    __ add(hash, scratch);
 
6050
  } else {
 
6051
    int32_t seed = masm->isolate()->heap()->HashSeed();
 
6052
    __ lea(scratch, Operand(character, seed));
 
6053
    __ shl(scratch, 10);
 
6054
    __ lea(hash, Operand(scratch, character, times_1, seed));
 
6055
  }
5912
6056
  // hash ^= hash >> 6;
5913
6057
  __ mov(scratch, hash);
5914
6058
  __ shr(scratch, 6);
5949
6093
  __ shl(scratch, 15);
5950
6094
  __ add(hash, scratch);
5951
6095
 
5952
 
  uint32_t kHashShiftCutOffMask = (1 << (32 - String::kHashShift)) - 1;
5953
 
  __ and_(hash, kHashShiftCutOffMask);
 
6096
  __ and_(hash, String::kHashBitMask);
5954
6097
 
5955
6098
  // if (hash == 0) hash = 27;
5956
6099
  Label hash_not_zero;
5957
 
  __ test(hash, hash);
5958
6100
  __ j(not_zero, &hash_not_zero, Label::kNear);
5959
 
  __ mov(hash, Immediate(27));
 
6101
  __ mov(hash, Immediate(StringHasher::kZeroHash));
5960
6102
  __ bind(&hash_not_zero);
5961
6103
}
5962
6104
 
5988
6130
  __ JumpIfNotSmi(edx, &runtime);
5989
6131
  __ sub(ecx, edx);
5990
6132
  __ cmp(ecx, FieldOperand(eax, String::kLengthOffset));
5991
 
  Label return_eax;
5992
 
  __ j(equal, &return_eax);
 
6133
  Label not_original_string;
 
6134
  __ j(not_equal, &not_original_string, Label::kNear);
 
6135
  Counters* counters = masm->isolate()->counters();
 
6136
  __ IncrementCounter(counters->sub_string_native(), 1);
 
6137
  __ ret(3 * kPointerSize);
 
6138
  __ bind(&not_original_string);
5993
6139
  // Special handling of sub-strings of length 1 and 2. One character strings
5994
6140
  // are handled in the runtime system (looked up in the single character
5995
6141
  // cache). Two character strings are looked for in the symbol cache.
5996
 
  __ SmiUntag(ecx);  // Result length is no longer smi.
5997
 
  __ cmp(ecx, 2);
 
6142
  __ cmp(ecx, Immediate(Smi::FromInt(2)));
5998
6143
  __ j(greater, &result_longer_than_two);
5999
6144
  __ j(less, &runtime);
6000
6145
 
6001
6146
  // Sub string of length 2 requested.
6002
6147
  // eax: string
6003
6148
  // ebx: instance type
6004
 
  // ecx: sub string length (value is 2)
 
6149
  // ecx: sub string length (smi, value is 2)
6005
6150
  // edx: from index (smi)
6006
6151
  __ JumpIfInstanceTypeIsNotSequentialAscii(ebx, ebx, &runtime);
6007
6152
 
6012
6157
             FieldOperand(eax, edx, times_1, SeqAsciiString::kHeaderSize + 1));
6013
6158
 
6014
6159
  // Try to lookup two character string in symbol table.
6015
 
  Label make_two_character_string;
 
6160
  Label combine_two_char, save_two_char;
6016
6161
  StringHelper::GenerateTwoCharacterSymbolTableProbe(
6017
 
      masm, ebx, ecx, eax, edx, edi,
6018
 
      &make_two_character_string, &make_two_character_string);
6019
 
  __ ret(3 * kPointerSize);
6020
 
 
6021
 
  __ bind(&make_two_character_string);
6022
 
  // Setup registers for allocating the two character string.
6023
 
  __ mov(eax, Operand(esp, 3 * kPointerSize));
6024
 
  __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
6025
 
  __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
6026
 
  __ Set(ecx, Immediate(2));
 
6162
      masm, ebx, ecx, eax, edx, edi, &combine_two_char, &save_two_char);
 
6163
  __ IncrementCounter(counters->sub_string_native(), 1);
 
6164
  __ ret(3 * kPointerSize);
 
6165
 
 
6166
  __ bind(&combine_two_char);
 
6167
  __ shl(ecx, kBitsPerByte);
 
6168
  __ or_(ebx, ecx);
 
6169
  __ bind(&save_two_char);
 
6170
  __ AllocateAsciiString(eax, 2, ecx, edx, &runtime);
 
6171
  __ mov_w(FieldOperand(eax, SeqAsciiString::kHeaderSize), ebx);
 
6172
  __ IncrementCounter(counters->sub_string_native(), 1);
 
6173
  __ ret(3 * kPointerSize);
 
6174
 
 
6175
  __ bind(&result_longer_than_two);
 
6176
  // eax: string
 
6177
  // ebx: instance type
 
6178
  // ecx: sub string length (smi)
 
6179
  // edx: from index (smi)
 
6180
  // Deal with different string types: update the index if necessary
 
6181
  // and put the underlying string into edi.
 
6182
  Label underlying_unpacked, sliced_string, seq_or_external_string;
 
6183
  // If the string is not indirect, it can only be sequential or external.
 
6184
  STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag));
 
6185
  STATIC_ASSERT(kIsIndirectStringMask != 0);
 
6186
  __ test(ebx, Immediate(kIsIndirectStringMask));
 
6187
  __ j(zero, &seq_or_external_string, Label::kNear);
 
6188
 
 
6189
  Factory* factory = masm->isolate()->factory();
 
6190
  __ test(ebx, Immediate(kSlicedNotConsMask));
 
6191
  __ j(not_zero, &sliced_string, Label::kNear);
 
6192
  // Cons string.  Check whether it is flat, then fetch first part.
 
6193
  // Flat cons strings have an empty second part.
 
6194
  __ cmp(FieldOperand(eax, ConsString::kSecondOffset),
 
6195
         factory->empty_string());
 
6196
  __ j(not_equal, &runtime);
 
6197
  __ mov(edi, FieldOperand(eax, ConsString::kFirstOffset));
 
6198
  // Update instance type.
 
6199
  __ mov(ebx, FieldOperand(edi, HeapObject::kMapOffset));
 
6200
  __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
 
6201
  __ jmp(&underlying_unpacked, Label::kNear);
 
6202
 
 
6203
  __ bind(&sliced_string);
 
6204
  // Sliced string.  Fetch parent and adjust start index by offset.
 
6205
  __ add(edx, FieldOperand(eax, SlicedString::kOffsetOffset));
 
6206
  __ mov(edi, FieldOperand(eax, SlicedString::kParentOffset));
 
6207
  // Update instance type.
 
6208
  __ mov(ebx, FieldOperand(edi, HeapObject::kMapOffset));
 
6209
  __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
 
6210
  __ jmp(&underlying_unpacked, Label::kNear);
 
6211
 
 
6212
  __ bind(&seq_or_external_string);
 
6213
  // Sequential or external string.  Just move string to the expected register.
 
6214
  __ mov(edi, eax);
 
6215
 
 
6216
  __ bind(&underlying_unpacked);
6027
6217
 
6028
6218
  if (FLAG_string_slices) {
6029
6219
    Label copy_routine;
6030
 
    // If coming from the make_two_character_string path, the string
6031
 
    // is too short to be sliced anyways.
6032
 
    STATIC_ASSERT(2 < SlicedString::kMinLength);
6033
 
    __ jmp(&copy_routine);
6034
 
    __ bind(&result_longer_than_two);
6035
 
 
6036
 
    // eax: string
6037
 
    // ebx: instance type
6038
 
    // ecx: sub string length
6039
 
    // edx: from index (smi)
6040
 
    Label allocate_slice, sliced_string, seq_or_external_string;
6041
 
    __ cmp(ecx, SlicedString::kMinLength);
 
6220
    // edi: underlying subject string
 
6221
    // ebx: instance type of underlying subject string
 
6222
    // edx: adjusted start index (smi)
 
6223
    // ecx: length (smi)
 
6224
    __ cmp(ecx, Immediate(Smi::FromInt(SlicedString::kMinLength)));
6042
6225
    // Short slice.  Copy instead of slicing.
6043
6226
    __ j(less, &copy_routine);
6044
 
    // If the string is not indirect, it can only be sequential or external.
6045
 
    STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag));
6046
 
    STATIC_ASSERT(kIsIndirectStringMask != 0);
6047
 
    __ test(ebx, Immediate(kIsIndirectStringMask));
6048
 
    __ j(zero, &seq_or_external_string, Label::kNear);
6049
 
 
6050
 
    Factory* factory = masm->isolate()->factory();
6051
 
    __ test(ebx, Immediate(kSlicedNotConsMask));
6052
 
    __ j(not_zero, &sliced_string, Label::kNear);
6053
 
    // Cons string.  Check whether it is flat, then fetch first part.
6054
 
    __ cmp(FieldOperand(eax, ConsString::kSecondOffset),
6055
 
           factory->empty_string());
6056
 
    __ j(not_equal, &runtime);
6057
 
    __ mov(edi, FieldOperand(eax, ConsString::kFirstOffset));
6058
 
    __ jmp(&allocate_slice, Label::kNear);
6059
 
 
6060
 
    __ bind(&sliced_string);
6061
 
    // Sliced string.  Fetch parent and correct start index by offset.
6062
 
    __ add(edx, FieldOperand(eax, SlicedString::kOffsetOffset));
6063
 
    __ mov(edi, FieldOperand(eax, SlicedString::kParentOffset));
6064
 
    __ jmp(&allocate_slice, Label::kNear);
6065
 
 
6066
 
    __ bind(&seq_or_external_string);
6067
 
    // Sequential or external string.  Just move string to the correct register.
6068
 
    __ mov(edi, eax);
6069
 
 
6070
 
    __ bind(&allocate_slice);
6071
 
    // edi: underlying subject string
6072
 
    // ebx: instance type of original subject string
6073
 
    // edx: offset
6074
 
    // ecx: length
6075
6227
    // Allocate new sliced string.  At this point we do not reload the instance
6076
6228
    // type including the string encoding because we simply rely on the info
6077
6229
    // provided by the original string.  It does not matter if the original
6088
6240
    __ AllocateTwoByteSlicedString(eax, ebx, no_reg, &runtime);
6089
6241
    __ bind(&set_slice_header);
6090
6242
    __ mov(FieldOperand(eax, SlicedString::kOffsetOffset), edx);
6091
 
    __ SmiTag(ecx);
6092
6243
    __ mov(FieldOperand(eax, SlicedString::kLengthOffset), ecx);
6093
6244
    __ mov(FieldOperand(eax, SlicedString::kParentOffset), edi);
6094
6245
    __ mov(FieldOperand(eax, SlicedString::kHashFieldOffset),
6095
6246
           Immediate(String::kEmptyHashField));
6096
 
    __ jmp(&return_eax);
 
6247
    __ IncrementCounter(counters->sub_string_native(), 1);
 
6248
    __ ret(3 * kPointerSize);
6097
6249
 
6098
6250
    __ bind(&copy_routine);
6099
 
  } else {
6100
 
    __ bind(&result_longer_than_two);
6101
6251
  }
6102
6252
 
6103
 
  // eax: string
6104
 
  // ebx: instance type
6105
 
  // ecx: result string length
6106
 
  // Check for flat ascii string
6107
 
  Label non_ascii_flat;
6108
 
  __ JumpIfInstanceTypeIsNotSequentialAscii(ebx, ebx, &non_ascii_flat);
6109
 
 
6110
 
  // Allocate the result.
6111
 
  __ AllocateAsciiString(eax, ecx, ebx, edx, edi, &runtime);
 
6253
  // edi: underlying subject string
 
6254
  // ebx: instance type of underlying subject string
 
6255
  // edx: adjusted start index (smi)
 
6256
  // ecx: length (smi)
 
6257
  // The subject string can only be external or sequential string of either
 
6258
  // encoding at this point.
 
6259
  Label two_byte_sequential, runtime_drop_two, sequential_string;
 
6260
  STATIC_ASSERT(kExternalStringTag != 0);
 
6261
  STATIC_ASSERT(kSeqStringTag == 0);
 
6262
  __ test_b(ebx, kExternalStringTag);
 
6263
  __ j(zero, &sequential_string);
 
6264
 
 
6265
  // Handle external string.
 
6266
  // Rule out short external strings.
 
6267
  STATIC_CHECK(kShortExternalStringTag != 0);
 
6268
  __ test_b(ebx, kShortExternalStringMask);
 
6269
  __ j(not_zero, &runtime);
 
6270
  __ mov(edi, FieldOperand(edi, ExternalString::kResourceDataOffset));
 
6271
  // Move the pointer so that offset-wise, it looks like a sequential string.
 
6272
  STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize);
 
6273
  __ sub(edi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
 
6274
 
 
6275
  __ bind(&sequential_string);
 
6276
  // Stash away (adjusted) index and (underlying) string.
 
6277
  __ push(edx);
 
6278
  __ push(edi);
 
6279
  __ SmiUntag(ecx);
 
6280
  STATIC_ASSERT((kAsciiStringTag & kStringEncodingMask) != 0);
 
6281
  __ test_b(ebx, kStringEncodingMask);
 
6282
  __ j(zero, &two_byte_sequential);
 
6283
 
 
6284
  // Sequential ASCII string.  Allocate the result.
 
6285
  __ AllocateAsciiString(eax, ecx, ebx, edx, edi, &runtime_drop_two);
6112
6286
 
6113
6287
  // eax: result string
6114
6288
  // ecx: result string length
6117
6291
  __ mov(edi, eax);
6118
6292
  __ add(edi, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
6119
6293
  // Load string argument and locate character of sub string start.
6120
 
  __ mov(esi, Operand(esp, 3 * kPointerSize));
6121
 
  __ add(esi, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
6122
 
  __ mov(ebx, Operand(esp, 2 * kPointerSize));  // from
 
6294
  __ pop(esi);
 
6295
  __ pop(ebx);
6123
6296
  __ SmiUntag(ebx);
6124
 
  __ add(esi, ebx);
 
6297
  __ lea(esi, FieldOperand(esi, ebx, times_1, SeqAsciiString::kHeaderSize));
6125
6298
 
6126
6299
  // eax: result string
6127
6300
  // ecx: result length
6130
6303
  // esi: character of sub string start
6131
6304
  StringHelper::GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, true);
6132
6305
  __ mov(esi, edx);  // Restore esi.
6133
 
  Counters* counters = masm->isolate()->counters();
6134
6306
  __ IncrementCounter(counters->sub_string_native(), 1);
6135
6307
  __ ret(3 * kPointerSize);
6136
6308
 
6137
 
  __ bind(&non_ascii_flat);
6138
 
  // eax: string
6139
 
  // ebx: instance type & kStringRepresentationMask | kStringEncodingMask
6140
 
  // ecx: result string length
6141
 
  // Check for flat two byte string
6142
 
  __ cmp(ebx, kSeqStringTag | kTwoByteStringTag);
6143
 
  __ j(not_equal, &runtime);
6144
 
 
6145
 
  // Allocate the result.
6146
 
  __ AllocateTwoByteString(eax, ecx, ebx, edx, edi, &runtime);
 
6309
  __ bind(&two_byte_sequential);
 
6310
  // Sequential two-byte string.  Allocate the result.
 
6311
  __ AllocateTwoByteString(eax, ecx, ebx, edx, edi, &runtime_drop_two);
6147
6312
 
6148
6313
  // eax: result string
6149
6314
  // ecx: result string length
6153
6318
  __ add(edi,
6154
6319
         Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
6155
6320
  // Load string argument and locate character of sub string start.
6156
 
  __ mov(esi, Operand(esp, 3 * kPointerSize));
6157
 
  __ add(esi, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
6158
 
  __ mov(ebx, Operand(esp, 2 * kPointerSize));  // from
 
6321
  __ pop(esi);
 
6322
  __ pop(ebx);
6159
6323
  // As from is a smi it is 2 times the value which matches the size of a two
6160
6324
  // byte character.
6161
6325
  STATIC_ASSERT(kSmiTag == 0);
6162
6326
  STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
6163
 
  __ add(esi, ebx);
 
6327
  __ lea(esi, FieldOperand(esi, ebx, times_1, SeqTwoByteString::kHeaderSize));
6164
6328
 
6165
6329
  // eax: result string
6166
6330
  // ecx: result length
6169
6333
  // esi: character of sub string start
6170
6334
  StringHelper::GenerateCopyCharactersREP(masm, edi, esi, ecx, ebx, false);
6171
6335
  __ mov(esi, edx);  // Restore esi.
6172
 
 
6173
 
  __ bind(&return_eax);
6174
6336
  __ IncrementCounter(counters->sub_string_native(), 1);
6175
6337
  __ ret(3 * kPointerSize);
6176
6338
 
 
6339
  // Drop pushed values on the stack before tail call.
 
6340
  __ bind(&runtime_drop_two);
 
6341
  __ Drop(2);
 
6342
 
6177
6343
  // Just jump to runtime to create the sub string.
6178
6344
  __ bind(&runtime);
6179
6345
  __ TailCallRuntime(Runtime::kSubString, 3, 1);
6328
6494
 
6329
6495
  __ bind(&not_same);
6330
6496
 
6331
 
  // Check that both objects are sequential ascii strings.
 
6497
  // Check that both objects are sequential ASCII strings.
6332
6498
  __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, &runtime);
6333
6499
 
6334
 
  // Compare flat ascii strings.
 
6500
  // Compare flat ASCII strings.
6335
6501
  // Drop arguments from the stack.
6336
6502
  __ pop(ecx);
6337
6503
  __ add(esp, Immediate(2 * kPointerSize));
6565
6731
}
6566
6732
 
6567
6733
 
 
6734
void ICCompareStub::GenerateKnownObjects(MacroAssembler* masm) {
 
6735
  Label miss;
 
6736
  __ mov(ecx, edx);
 
6737
  __ and_(ecx, eax);
 
6738
  __ JumpIfSmi(ecx, &miss, Label::kNear);
 
6739
 
 
6740
  __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
 
6741
  __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
 
6742
  __ cmp(ecx, known_map_);
 
6743
  __ j(not_equal, &miss, Label::kNear);
 
6744
  __ cmp(ebx, known_map_);
 
6745
  __ j(not_equal, &miss, Label::kNear);
 
6746
 
 
6747
  __ sub(eax, edx);
 
6748
  __ ret(0);
 
6749
 
 
6750
  __ bind(&miss);
 
6751
  GenerateMiss(masm);
 
6752
}
 
6753
 
 
6754
 
6568
6755
void ICCompareStub::GenerateMiss(MacroAssembler* masm) {
6569
 
  // Save the registers.
6570
 
  __ pop(ecx);
6571
 
  __ push(edx);
6572
 
  __ push(eax);
6573
 
  __ push(ecx);
6574
 
 
6575
6756
  {
6576
6757
    // Call the runtime system in a fresh internal frame.
6577
6758
    ExternalReference miss = ExternalReference(IC_Utility(IC::kCompareIC_Miss),
6578
6759
                                               masm->isolate());
6579
6760
    FrameScope scope(masm, StackFrame::INTERNAL);
6580
 
    __ push(edx);
 
6761
    __ push(edx);  // Preserve edx and eax.
 
6762
    __ push(eax);
 
6763
    __ push(edx);  // And also use them as the arguments.
6581
6764
    __ push(eax);
6582
6765
    __ push(Immediate(Smi::FromInt(op_)));
6583
6766
    __ CallExternalReference(miss, 3);
 
6767
    // Compute the entry point of the rewritten stub.
 
6768
    __ lea(edi, FieldOperand(eax, Code::kHeaderSize));
 
6769
    __ pop(eax);
 
6770
    __ pop(edx);
6584
6771
  }
6585
6772
 
6586
 
  // Compute the entry point of the rewritten stub.
6587
 
  __ lea(edi, FieldOperand(eax, Code::kHeaderSize));
6588
 
 
6589
 
  // Restore registers.
6590
 
  __ pop(ecx);
6591
 
  __ pop(eax);
6592
 
  __ pop(edx);
6593
 
  __ push(ecx);
6594
 
 
6595
6773
  // Do a tail call to the rewritten stub.
6596
6774
  __ jmp(edi);
6597
6775
}