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

Side by Side Diff: src/ia32/lithium-codegen-ia32.cc

Issue 71163006: Merge bleeding_edge r17376:17693. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Fix all.gyp Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-gap-resolver-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 1025 matching lines...) Expand 10 before | Expand all | Expand 10 after
1036 ASSERT(environment->HasBeenRegistered()); 1036 ASSERT(environment->HasBeenRegistered());
1037 int id = environment->deoptimization_index(); 1037 int id = environment->deoptimization_index();
1038 ASSERT(info()->IsOptimizing() || info()->IsStub()); 1038 ASSERT(info()->IsOptimizing() || info()->IsStub());
1039 Address entry = 1039 Address entry =
1040 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); 1040 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type);
1041 if (entry == NULL) { 1041 if (entry == NULL) {
1042 Abort(kBailoutWasNotPrepared); 1042 Abort(kBailoutWasNotPrepared);
1043 return; 1043 return;
1044 } 1044 }
1045 1045
1046 if (FLAG_deopt_every_n_times != 0 && !info()->IsStub()) { 1046 if (DeoptEveryNTimes()) {
1047 ExternalReference count = ExternalReference::stress_deopt_count(isolate()); 1047 ExternalReference count = ExternalReference::stress_deopt_count(isolate());
1048 Label no_deopt; 1048 Label no_deopt;
1049 __ pushfd(); 1049 __ pushfd();
1050 __ push(eax); 1050 __ push(eax);
1051 __ mov(eax, Operand::StaticVariable(count)); 1051 __ mov(eax, Operand::StaticVariable(count));
1052 __ sub(eax, Immediate(1)); 1052 __ sub(eax, Immediate(1));
1053 __ j(not_zero, &no_deopt, Label::kNear); 1053 __ j(not_zero, &no_deopt, Label::kNear);
1054 if (FLAG_trap_on_deopt) __ int3(); 1054 if (FLAG_trap_on_deopt) __ int3();
1055 __ mov(eax, Immediate(FLAG_deopt_every_n_times)); 1055 __ mov(eax, Immediate(FLAG_deopt_every_n_times));
1056 __ mov(Operand::StaticVariable(count), eax); 1056 __ mov(Operand::StaticVariable(count), eax);
(...skipping 894 matching lines...) Expand 10 before | Expand all | Expand 10 after
1951 __ pinsrd(res, Operand(temp), 1); 1951 __ pinsrd(res, Operand(temp), 1);
1952 } 1952 }
1953 } else { 1953 } else {
1954 __ Set(temp, Immediate(upper)); 1954 __ Set(temp, Immediate(upper));
1955 __ movd(res, Operand(temp)); 1955 __ movd(res, Operand(temp));
1956 __ psllq(res, 32); 1956 __ psllq(res, 32);
1957 if (lower != 0) { 1957 if (lower != 0) {
1958 XMMRegister xmm_scratch = double_scratch0(); 1958 XMMRegister xmm_scratch = double_scratch0();
1959 __ Set(temp, Immediate(lower)); 1959 __ Set(temp, Immediate(lower));
1960 __ movd(xmm_scratch, Operand(temp)); 1960 __ movd(xmm_scratch, Operand(temp));
1961 __ por(res, xmm_scratch); 1961 __ orps(res, xmm_scratch);
1962 } 1962 }
1963 } 1963 }
1964 } 1964 }
1965 } 1965 }
1966 } 1966 }
1967 1967
1968 1968
1969 void LCodeGen::DoConstantE(LConstantE* instr) { 1969 void LCodeGen::DoConstantE(LConstantE* instr) {
1970 __ lea(ToRegister(instr->result()), Operand::StaticVariable(instr->value())); 1970 __ lea(ToRegister(instr->result()), Operand::StaticVariable(instr->value()));
1971 } 1971 }
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
2040 if (index->value() == 0) { 2040 if (index->value() == 0) {
2041 __ mov(result, FieldOperand(object, JSDate::kValueOffset)); 2041 __ mov(result, FieldOperand(object, JSDate::kValueOffset));
2042 } else { 2042 } else {
2043 if (index->value() < JSDate::kFirstUncachedField) { 2043 if (index->value() < JSDate::kFirstUncachedField) {
2044 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); 2044 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
2045 __ mov(scratch, Operand::StaticVariable(stamp)); 2045 __ mov(scratch, Operand::StaticVariable(stamp));
2046 __ cmp(scratch, FieldOperand(object, JSDate::kCacheStampOffset)); 2046 __ cmp(scratch, FieldOperand(object, JSDate::kCacheStampOffset));
2047 __ j(not_equal, &runtime, Label::kNear); 2047 __ j(not_equal, &runtime, Label::kNear);
2048 __ mov(result, FieldOperand(object, JSDate::kValueOffset + 2048 __ mov(result, FieldOperand(object, JSDate::kValueOffset +
2049 kPointerSize * index->value())); 2049 kPointerSize * index->value()));
2050 __ jmp(&done); 2050 __ jmp(&done, Label::kNear);
2051 } 2051 }
2052 __ bind(&runtime); 2052 __ bind(&runtime);
2053 __ PrepareCallCFunction(2, scratch); 2053 __ PrepareCallCFunction(2, scratch);
2054 __ mov(Operand(esp, 0), object); 2054 __ mov(Operand(esp, 0), object);
2055 __ mov(Operand(esp, 1 * kPointerSize), Immediate(index)); 2055 __ mov(Operand(esp, 1 * kPointerSize), Immediate(index));
2056 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); 2056 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
2057 __ bind(&done); 2057 __ bind(&done);
2058 } 2058 }
2059 } 2059 }
2060 2060
2061 2061
2062 Operand LCodeGen::BuildSeqStringOperand(Register string,
2063 LOperand* index,
2064 String::Encoding encoding) {
2065 if (index->IsConstantOperand()) {
2066 int offset = ToRepresentation(LConstantOperand::cast(index),
2067 Representation::Integer32());
2068 if (encoding == String::TWO_BYTE_ENCODING) {
2069 offset *= kUC16Size;
2070 }
2071 STATIC_ASSERT(kCharSize == 1);
2072 return FieldOperand(string, SeqString::kHeaderSize + offset);
2073 }
2074 return FieldOperand(
2075 string, ToRegister(index),
2076 encoding == String::ONE_BYTE_ENCODING ? times_1 : times_2,
2077 SeqString::kHeaderSize);
2078 }
2079
2080
2081 void LCodeGen::DoSeqStringGetChar(LSeqStringGetChar* instr) {
2082 String::Encoding encoding = instr->hydrogen()->encoding();
2083 Register result = ToRegister(instr->result());
2084 Register string = ToRegister(instr->string());
2085
2086 if (FLAG_debug_code) {
2087 __ push(string);
2088 __ mov(string, FieldOperand(string, HeapObject::kMapOffset));
2089 __ movzx_b(string, FieldOperand(string, Map::kInstanceTypeOffset));
2090
2091 __ and_(string, Immediate(kStringRepresentationMask | kStringEncodingMask));
2092 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
2093 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
2094 __ cmp(string, Immediate(encoding == String::ONE_BYTE_ENCODING
2095 ? one_byte_seq_type : two_byte_seq_type));
2096 __ Check(equal, kUnexpectedStringType);
2097 __ pop(string);
2098 }
2099
2100 Operand operand = BuildSeqStringOperand(string, instr->index(), encoding);
2101 if (encoding == String::ONE_BYTE_ENCODING) {
2102 __ movzx_b(result, operand);
2103 } else {
2104 __ movzx_w(result, operand);
2105 }
2106 }
2107
2108
2062 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { 2109 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
2110 String::Encoding encoding = instr->hydrogen()->encoding();
2063 Register string = ToRegister(instr->string()); 2111 Register string = ToRegister(instr->string());
2064 Register index = ToRegister(instr->index());
2065 Register value = ToRegister(instr->value());
2066 String::Encoding encoding = instr->encoding();
2067 2112
2068 if (FLAG_debug_code) { 2113 if (FLAG_debug_code) {
2069 __ push(value); 2114 __ push(string);
2070 __ mov(value, FieldOperand(string, HeapObject::kMapOffset)); 2115 __ mov(string, FieldOperand(string, HeapObject::kMapOffset));
2071 __ movzx_b(value, FieldOperand(value, Map::kInstanceTypeOffset)); 2116 __ movzx_b(string, FieldOperand(string, Map::kInstanceTypeOffset));
2072 2117
2073 __ and_(value, Immediate(kStringRepresentationMask | kStringEncodingMask)); 2118 __ and_(string, Immediate(kStringRepresentationMask | kStringEncodingMask));
2074 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; 2119 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
2075 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; 2120 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
2076 __ cmp(value, Immediate(encoding == String::ONE_BYTE_ENCODING 2121 __ cmp(string, Immediate(encoding == String::ONE_BYTE_ENCODING
2077 ? one_byte_seq_type : two_byte_seq_type)); 2122 ? one_byte_seq_type : two_byte_seq_type));
2078 __ Check(equal, kUnexpectedStringType); 2123 __ Check(equal, kUnexpectedStringType);
2079 __ pop(value); 2124 __ pop(string);
2080 } 2125 }
2081 2126
2082 if (encoding == String::ONE_BYTE_ENCODING) { 2127 Operand operand = BuildSeqStringOperand(string, instr->index(), encoding);
2083 __ mov_b(FieldOperand(string, index, times_1, SeqString::kHeaderSize), 2128 if (instr->value()->IsConstantOperand()) {
2084 value); 2129 int value = ToRepresentation(LConstantOperand::cast(instr->value()),
2130 Representation::Integer32());
2131 ASSERT_LE(0, value);
2132 if (encoding == String::ONE_BYTE_ENCODING) {
2133 ASSERT_LE(value, String::kMaxOneByteCharCode);
2134 __ mov_b(operand, static_cast<int8_t>(value));
2135 } else {
2136 ASSERT_LE(value, String::kMaxUtf16CodeUnit);
2137 __ mov_w(operand, static_cast<int16_t>(value));
2138 }
2085 } else { 2139 } else {
2086 __ mov_w(FieldOperand(string, index, times_2, SeqString::kHeaderSize), 2140 Register value = ToRegister(instr->value());
2087 value); 2141 if (encoding == String::ONE_BYTE_ENCODING) {
2142 __ mov_b(operand, value);
2143 } else {
2144 __ mov_w(operand, value);
2145 }
2088 } 2146 }
2089 } 2147 }
2090 2148
2091 2149
2092 void LCodeGen::DoThrow(LThrow* instr) { 2150 void LCodeGen::DoThrow(LThrow* instr) {
2093 __ push(ToOperand(instr->value())); 2151 __ push(ToOperand(instr->value()));
2094 ASSERT(ToRegister(instr->context()).is(esi)); 2152 ASSERT(ToRegister(instr->context()).is(esi));
2095 CallRuntime(Runtime::kThrow, 1, instr); 2153 CallRuntime(Runtime::kThrow, 1, instr);
2096 2154
2097 if (FLAG_debug_code) { 2155 if (FLAG_debug_code) {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
2177 } else { 2235 } else {
2178 // Since we operate on +0 and/or -0, addsd and andsd have the same effect. 2236 // Since we operate on +0 and/or -0, addsd and andsd have the same effect.
2179 __ addsd(left_reg, right_reg); 2237 __ addsd(left_reg, right_reg);
2180 } 2238 }
2181 __ jmp(&return_left, Label::kNear); 2239 __ jmp(&return_left, Label::kNear);
2182 2240
2183 __ bind(&check_nan_left); 2241 __ bind(&check_nan_left);
2184 __ ucomisd(left_reg, left_reg); // NaN check. 2242 __ ucomisd(left_reg, left_reg); // NaN check.
2185 __ j(parity_even, &return_left, Label::kNear); // left == NaN. 2243 __ j(parity_even, &return_left, Label::kNear); // left == NaN.
2186 __ bind(&return_right); 2244 __ bind(&return_right);
2187 __ movsd(left_reg, right_reg); 2245 __ movaps(left_reg, right_reg);
2188 2246
2189 __ bind(&return_left); 2247 __ bind(&return_left);
2190 } 2248 }
2191 } 2249 }
2192 2250
2193 2251
2194 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { 2252 void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
2195 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { 2253 if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
2196 CpuFeatureScope scope(masm(), SSE2); 2254 CpuFeatureScope scope(masm(), SSE2);
2197 XMMRegister left = ToDoubleRegister(instr->left()); 2255 XMMRegister left = ToDoubleRegister(instr->left());
(...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after
2582 __ ucomisd(input_reg, input_reg); 2640 __ ucomisd(input_reg, input_reg);
2583 EmitFalseBranch(instr, parity_odd); 2641 EmitFalseBranch(instr, parity_odd);
2584 } else { 2642 } else {
2585 // Put the value to the top of stack 2643 // Put the value to the top of stack
2586 X87Register src = ToX87Register(instr->object()); 2644 X87Register src = ToX87Register(instr->object());
2587 X87LoadForUsage(src); 2645 X87LoadForUsage(src);
2588 __ fld(0); 2646 __ fld(0);
2589 __ fld(0); 2647 __ fld(0);
2590 __ FCmp(); 2648 __ FCmp();
2591 Label ok; 2649 Label ok;
2592 __ j(parity_even, &ok); 2650 __ j(parity_even, &ok, Label::kNear);
2593 __ fstp(0); 2651 __ fstp(0);
2594 EmitFalseBranch(instr, no_condition); 2652 EmitFalseBranch(instr, no_condition);
2595 __ bind(&ok); 2653 __ bind(&ok);
2596 } 2654 }
2597 2655
2598 2656
2599 __ sub(esp, Immediate(kDoubleSize)); 2657 __ sub(esp, Immediate(kDoubleSize));
2600 if (use_sse2) { 2658 if (use_sse2) {
2601 CpuFeatureScope scope(masm(), SSE2); 2659 CpuFeatureScope scope(masm(), SSE2);
2602 XMMRegister input_reg = ToDoubleRegister(instr->object()); 2660 XMMRegister input_reg = ToDoubleRegister(instr->object());
2603 __ movsd(MemOperand(esp, 0), input_reg); 2661 __ movsd(MemOperand(esp, 0), input_reg);
2604 } else { 2662 } else {
2605 __ fstp_d(MemOperand(esp, 0)); 2663 __ fstp_d(MemOperand(esp, 0));
2606 } 2664 }
2607 2665
2608 __ add(esp, Immediate(kDoubleSize)); 2666 __ add(esp, Immediate(kDoubleSize));
2609 int offset = sizeof(kHoleNanUpper32); 2667 int offset = sizeof(kHoleNanUpper32);
2610 __ cmp(MemOperand(esp, -offset), Immediate(kHoleNanUpper32)); 2668 __ cmp(MemOperand(esp, -offset), Immediate(kHoleNanUpper32));
2611 EmitBranch(instr, equal); 2669 EmitBranch(instr, equal);
2612 } 2670 }
2613 2671
2614 2672
2673 void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) {
2674 Representation rep = instr->hydrogen()->value()->representation();
2675 ASSERT(!rep.IsInteger32());
2676 Register scratch = ToRegister(instr->temp());
2677
2678 if (rep.IsDouble()) {
2679 CpuFeatureScope use_sse2(masm(), SSE2);
2680 XMMRegister value = ToDoubleRegister(instr->value());
2681 XMMRegister xmm_scratch = double_scratch0();
2682 __ xorps(xmm_scratch, xmm_scratch);
2683 __ ucomisd(xmm_scratch, value);
2684 EmitFalseBranch(instr, not_equal);
2685 __ movmskpd(scratch, value);
2686 __ test(scratch, Immediate(1));
2687 EmitBranch(instr, not_zero);
2688 } else {
2689 Register value = ToRegister(instr->value());
2690 Handle<Map> map = masm()->isolate()->factory()->heap_number_map();
2691 __ CheckMap(value, map, instr->FalseLabel(chunk()), DO_SMI_CHECK);
2692 __ cmp(FieldOperand(value, HeapNumber::kExponentOffset),
2693 Immediate(0x80000000));
2694 EmitFalseBranch(instr, not_equal);
2695 __ cmp(FieldOperand(value, HeapNumber::kMantissaOffset),
2696 Immediate(0x00000000));
2697 EmitBranch(instr, equal);
2698 }
2699 }
2700
2701
2615 Condition LCodeGen::EmitIsObject(Register input, 2702 Condition LCodeGen::EmitIsObject(Register input,
2616 Register temp1, 2703 Register temp1,
2617 Label* is_not_object, 2704 Label* is_not_object,
2618 Label* is_object) { 2705 Label* is_object) {
2619 __ JumpIfSmi(input, is_not_object); 2706 __ JumpIfSmi(input, is_not_object);
2620 2707
2621 __ cmp(input, isolate()->factory()->null_value()); 2708 __ cmp(input, isolate()->factory()->null_value());
2622 __ j(equal, is_object); 2709 __ j(equal, is_object);
2623 2710
2624 __ mov(temp1, FieldOperand(input, HeapObject::kMapOffset)); 2711 __ mov(temp1, FieldOperand(input, HeapObject::kMapOffset));
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
2906 }; 2993 };
2907 2994
2908 DeferredInstanceOfKnownGlobal* deferred; 2995 DeferredInstanceOfKnownGlobal* deferred;
2909 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr, x87_stack_); 2996 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr, x87_stack_);
2910 2997
2911 Label done, false_result; 2998 Label done, false_result;
2912 Register object = ToRegister(instr->value()); 2999 Register object = ToRegister(instr->value());
2913 Register temp = ToRegister(instr->temp()); 3000 Register temp = ToRegister(instr->temp());
2914 3001
2915 // A Smi is not an instance of anything. 3002 // A Smi is not an instance of anything.
2916 __ JumpIfSmi(object, &false_result); 3003 __ JumpIfSmi(object, &false_result, Label::kNear);
2917 3004
2918 // This is the inlined call site instanceof cache. The two occurences of the 3005 // This is the inlined call site instanceof cache. The two occurences of the
2919 // hole value will be patched to the last map/result pair generated by the 3006 // hole value will be patched to the last map/result pair generated by the
2920 // instanceof stub. 3007 // instanceof stub.
2921 Label cache_miss; 3008 Label cache_miss;
2922 Register map = ToRegister(instr->temp()); 3009 Register map = ToRegister(instr->temp());
2923 __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); 3010 __ mov(map, FieldOperand(object, HeapObject::kMapOffset));
2924 __ bind(deferred->map_check()); // Label for calculating code patching. 3011 __ bind(deferred->map_check()); // Label for calculating code patching.
2925 Handle<Cell> cache_cell = factory()->NewCell(factory()->the_hole_value()); 3012 Handle<Cell> cache_cell = factory()->NewCell(factory()->the_hole_value());
2926 __ cmp(map, Operand::ForCell(cache_cell)); // Patched to cached map. 3013 __ cmp(map, Operand::ForCell(cache_cell)); // Patched to cached map.
2927 __ j(not_equal, &cache_miss, Label::kNear); 3014 __ j(not_equal, &cache_miss, Label::kNear);
2928 __ mov(eax, factory()->the_hole_value()); // Patched to either true or false. 3015 __ mov(eax, factory()->the_hole_value()); // Patched to either true or false.
2929 __ jmp(&done); 3016 __ jmp(&done, Label::kNear);
2930 3017
2931 // The inlined call site cache did not match. Check for null and string 3018 // The inlined call site cache did not match. Check for null and string
2932 // before calling the deferred code. 3019 // before calling the deferred code.
2933 __ bind(&cache_miss); 3020 __ bind(&cache_miss);
2934 // Null is not an instance of anything. 3021 // Null is not an instance of anything.
2935 __ cmp(object, factory()->null_value()); 3022 __ cmp(object, factory()->null_value());
2936 __ j(equal, &false_result); 3023 __ j(equal, &false_result, Label::kNear);
2937 3024
2938 // String values are not instances of anything. 3025 // String values are not instances of anything.
2939 Condition is_string = masm_->IsObjectStringType(object, temp, temp); 3026 Condition is_string = masm_->IsObjectStringType(object, temp, temp);
2940 __ j(is_string, &false_result); 3027 __ j(is_string, &false_result, Label::kNear);
2941 3028
2942 // Go to the deferred code. 3029 // Go to the deferred code.
2943 __ jmp(deferred->entry()); 3030 __ jmp(deferred->entry());
2944 3031
2945 __ bind(&false_result); 3032 __ bind(&false_result);
2946 __ mov(ToRegister(instr->result()), factory()->false_value()); 3033 __ mov(ToRegister(instr->result()), factory()->false_value());
2947 3034
2948 // Here result has either true or false. Deferred code also produces true or 3035 // Here result has either true or false. Deferred code also produces true or
2949 // false object. 3036 // false object.
2950 __ bind(deferred->exit()); 3037 __ bind(deferred->exit());
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
3075 } 3162 }
3076 int no_frame_start = -1; 3163 int no_frame_start = -1;
3077 if (NeedsEagerFrame()) { 3164 if (NeedsEagerFrame()) {
3078 __ mov(esp, ebp); 3165 __ mov(esp, ebp);
3079 __ pop(ebp); 3166 __ pop(ebp);
3080 no_frame_start = masm_->pc_offset(); 3167 no_frame_start = masm_->pc_offset();
3081 } 3168 }
3082 if (dynamic_frame_alignment_) { 3169 if (dynamic_frame_alignment_) {
3083 Label no_padding; 3170 Label no_padding;
3084 __ cmp(edx, Immediate(kNoAlignmentPadding)); 3171 __ cmp(edx, Immediate(kNoAlignmentPadding));
3085 __ j(equal, &no_padding); 3172 __ j(equal, &no_padding, Label::kNear);
3086 3173
3087 EmitReturn(instr, true); 3174 EmitReturn(instr, true);
3088 __ bind(&no_padding); 3175 __ bind(&no_padding);
3089 } 3176 }
3090 3177
3091 EmitReturn(instr, false); 3178 EmitReturn(instr, false);
3092 if (no_frame_start != -1) { 3179 if (no_frame_start != -1) {
3093 info()->AddNoFrameRange(no_frame_start, masm_->pc_offset()); 3180 info()->AddNoFrameRange(no_frame_start, masm_->pc_offset());
3094 } 3181 }
3095 } 3182 }
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
3208 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { 3295 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
3209 HObjectAccess access = instr->hydrogen()->access(); 3296 HObjectAccess access = instr->hydrogen()->access();
3210 int offset = access.offset(); 3297 int offset = access.offset();
3211 3298
3212 if (access.IsExternalMemory()) { 3299 if (access.IsExternalMemory()) {
3213 Register result = ToRegister(instr->result()); 3300 Register result = ToRegister(instr->result());
3214 MemOperand operand = instr->object()->IsConstantOperand() 3301 MemOperand operand = instr->object()->IsConstantOperand()
3215 ? MemOperand::StaticVariable(ToExternalReference( 3302 ? MemOperand::StaticVariable(ToExternalReference(
3216 LConstantOperand::cast(instr->object()))) 3303 LConstantOperand::cast(instr->object())))
3217 : MemOperand(ToRegister(instr->object()), offset); 3304 : MemOperand(ToRegister(instr->object()), offset);
3218 if (access.representation().IsByte()) { 3305 __ Load(result, operand, access.representation());
3219 ASSERT(instr->hydrogen()->representation().IsInteger32());
3220 __ movzx_b(result, operand);
3221 } else {
3222 __ mov(result, operand);
3223 }
3224 return; 3306 return;
3225 } 3307 }
3226 3308
3227 Register object = ToRegister(instr->object()); 3309 Register object = ToRegister(instr->object());
3228 if (FLAG_track_double_fields && 3310 if (FLAG_track_double_fields &&
3229 instr->hydrogen()->representation().IsDouble()) { 3311 instr->hydrogen()->representation().IsDouble()) {
3230 if (CpuFeatures::IsSupported(SSE2)) { 3312 if (CpuFeatures::IsSupported(SSE2)) {
3231 CpuFeatureScope scope(masm(), SSE2); 3313 CpuFeatureScope scope(masm(), SSE2);
3232 XMMRegister result = ToDoubleRegister(instr->result()); 3314 XMMRegister result = ToDoubleRegister(instr->result());
3233 __ movsd(result, FieldOperand(object, offset)); 3315 __ movsd(result, FieldOperand(object, offset));
3234 } else { 3316 } else {
3235 X87Mov(ToX87Register(instr->result()), FieldOperand(object, offset)); 3317 X87Mov(ToX87Register(instr->result()), FieldOperand(object, offset));
3236 } 3318 }
3237 return; 3319 return;
3238 } 3320 }
3239 3321
3240 Register result = ToRegister(instr->result()); 3322 Register result = ToRegister(instr->result());
3241 if (!access.IsInobject()) { 3323 if (!access.IsInobject()) {
3242 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); 3324 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset));
3243 object = result; 3325 object = result;
3244 } 3326 }
3245 if (access.representation().IsByte()) { 3327 __ Load(result, FieldOperand(object, offset), access.representation());
3246 ASSERT(instr->hydrogen()->representation().IsInteger32());
3247 __ movzx_b(result, FieldOperand(object, offset));
3248 } else {
3249 __ mov(result, FieldOperand(object, offset));
3250 }
3251 } 3328 }
3252 3329
3253 3330
3254 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { 3331 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) {
3255 ASSERT(!operand->IsDoubleRegister()); 3332 ASSERT(!operand->IsDoubleRegister());
3256 if (operand->IsConstantOperand()) { 3333 if (operand->IsConstantOperand()) {
3257 Handle<Object> object = ToHandle(LConstantOperand::cast(operand)); 3334 Handle<Object> object = ToHandle(LConstantOperand::cast(operand));
3258 AllowDeferredHandleDereference smi_check; 3335 AllowDeferredHandleDereference smi_check;
3259 if (object->IsSmi()) { 3336 if (object->IsSmi()) {
3260 __ Push(Handle<Smi>::cast(object)); 3337 __ Push(Handle<Smi>::cast(object));
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after
3593 3670
3594 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { 3671 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
3595 Register receiver = ToRegister(instr->receiver()); 3672 Register receiver = ToRegister(instr->receiver());
3596 Register function = ToRegister(instr->function()); 3673 Register function = ToRegister(instr->function());
3597 Register scratch = ToRegister(instr->temp()); 3674 Register scratch = ToRegister(instr->temp());
3598 3675
3599 // If the receiver is null or undefined, we have to pass the global 3676 // If the receiver is null or undefined, we have to pass the global
3600 // object as a receiver to normal functions. Values have to be 3677 // object as a receiver to normal functions. Values have to be
3601 // passed unchanged to builtins and strict-mode functions. 3678 // passed unchanged to builtins and strict-mode functions.
3602 Label global_object, receiver_ok; 3679 Label global_object, receiver_ok;
3680 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
3603 3681
3604 // Do not transform the receiver to object for strict mode 3682 // Do not transform the receiver to object for strict mode
3605 // functions. 3683 // functions.
3606 __ mov(scratch, 3684 __ mov(scratch,
3607 FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); 3685 FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
3608 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset), 3686 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset),
3609 1 << SharedFunctionInfo::kStrictModeBitWithinByte); 3687 1 << SharedFunctionInfo::kStrictModeBitWithinByte);
3610 __ j(not_equal, &receiver_ok); // A near jump is not sufficient here! 3688 __ j(not_equal, &receiver_ok, dist);
3611 3689
3612 // Do not transform the receiver to object for builtins. 3690 // Do not transform the receiver to object for builtins.
3613 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset), 3691 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset),
3614 1 << SharedFunctionInfo::kNativeBitWithinByte); 3692 1 << SharedFunctionInfo::kNativeBitWithinByte);
3615 __ j(not_equal, &receiver_ok); 3693 __ j(not_equal, &receiver_ok, dist);
3616 3694
3617 // Normal function. Replace undefined or null with global receiver. 3695 // Normal function. Replace undefined or null with global receiver.
3618 __ cmp(receiver, factory()->null_value()); 3696 __ cmp(receiver, factory()->null_value());
3619 __ j(equal, &global_object, Label::kNear); 3697 __ j(equal, &global_object, Label::kNear);
3620 __ cmp(receiver, factory()->undefined_value()); 3698 __ cmp(receiver, factory()->undefined_value());
3621 __ j(equal, &global_object, Label::kNear); 3699 __ j(equal, &global_object, Label::kNear);
3622 3700
3623 // The receiver should be a JS object. 3701 // The receiver should be a JS object.
3624 __ test(receiver, Immediate(kSmiTagMask)); 3702 __ test(receiver, Immediate(kSmiTagMask));
3625 DeoptimizeIf(equal, instr->environment()); 3703 DeoptimizeIf(equal, instr->environment());
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
3814 3892
3815 // Preserve the value of all registers. 3893 // Preserve the value of all registers.
3816 PushSafepointRegistersScope scope(this); 3894 PushSafepointRegistersScope scope(this);
3817 3895
3818 __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 3896 __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset));
3819 // Check the sign of the argument. If the argument is positive, just 3897 // Check the sign of the argument. If the argument is positive, just
3820 // return it. We do not need to patch the stack since |input| and 3898 // return it. We do not need to patch the stack since |input| and
3821 // |result| are the same register and |input| will be restored 3899 // |result| are the same register and |input| will be restored
3822 // unchanged by popping safepoint registers. 3900 // unchanged by popping safepoint registers.
3823 __ test(tmp, Immediate(HeapNumber::kSignMask)); 3901 __ test(tmp, Immediate(HeapNumber::kSignMask));
3824 __ j(zero, &done); 3902 __ j(zero, &done, Label::kNear);
3825 3903
3826 __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow); 3904 __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow);
3827 __ jmp(&allocated, Label::kNear); 3905 __ jmp(&allocated, Label::kNear);
3828 3906
3829 // Slow case: Call the runtime system to do the number allocation. 3907 // Slow case: Call the runtime system to do the number allocation.
3830 __ bind(&slow); 3908 __ bind(&slow);
3831 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, 3909 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0,
3832 instr, instr->context()); 3910 instr, instr->context());
3833 // Set the pointer to the new heap number in tmp. 3911 // Set the pointer to the new heap number in tmp.
3834 if (!tmp.is(eax)) __ mov(tmp, eax); 3912 if (!tmp.is(eax)) __ mov(tmp, eax);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
3876 3954
3877 ASSERT(instr->value()->Equals(instr->result())); 3955 ASSERT(instr->value()->Equals(instr->result()));
3878 Representation r = instr->hydrogen()->value()->representation(); 3956 Representation r = instr->hydrogen()->value()->representation();
3879 3957
3880 CpuFeatureScope scope(masm(), SSE2); 3958 CpuFeatureScope scope(masm(), SSE2);
3881 if (r.IsDouble()) { 3959 if (r.IsDouble()) {
3882 XMMRegister scratch = double_scratch0(); 3960 XMMRegister scratch = double_scratch0();
3883 XMMRegister input_reg = ToDoubleRegister(instr->value()); 3961 XMMRegister input_reg = ToDoubleRegister(instr->value());
3884 __ xorps(scratch, scratch); 3962 __ xorps(scratch, scratch);
3885 __ subsd(scratch, input_reg); 3963 __ subsd(scratch, input_reg);
3886 __ pand(input_reg, scratch); 3964 __ andps(input_reg, scratch);
3887 } else if (r.IsSmiOrInteger32()) { 3965 } else if (r.IsSmiOrInteger32()) {
3888 EmitIntegerMathAbs(instr); 3966 EmitIntegerMathAbs(instr);
3889 } else { // Tagged case. 3967 } else { // Tagged case.
3890 DeferredMathAbsTaggedHeapNumber* deferred = 3968 DeferredMathAbsTaggedHeapNumber* deferred =
3891 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr, x87_stack_); 3969 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr, x87_stack_);
3892 Register input_reg = ToRegister(instr->value()); 3970 Register input_reg = ToRegister(instr->value());
3893 // Smi check. 3971 // Smi check.
3894 __ JumpIfNotSmi(input_reg, deferred->entry()); 3972 __ JumpIfNotSmi(input_reg, deferred->entry());
3895 EmitIntegerMathAbs(instr); 3973 EmitIntegerMathAbs(instr);
3896 __ bind(deferred->exit()); 3974 __ bind(deferred->exit());
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
3968 CpuFeatureScope scope(masm(), SSE2); 4046 CpuFeatureScope scope(masm(), SSE2);
3969 Register output_reg = ToRegister(instr->result()); 4047 Register output_reg = ToRegister(instr->result());
3970 XMMRegister input_reg = ToDoubleRegister(instr->value()); 4048 XMMRegister input_reg = ToDoubleRegister(instr->value());
3971 XMMRegister xmm_scratch = double_scratch0(); 4049 XMMRegister xmm_scratch = double_scratch0();
3972 XMMRegister input_temp = ToDoubleRegister(instr->temp()); 4050 XMMRegister input_temp = ToDoubleRegister(instr->temp());
3973 ExternalReference one_half = ExternalReference::address_of_one_half(); 4051 ExternalReference one_half = ExternalReference::address_of_one_half();
3974 ExternalReference minus_one_half = 4052 ExternalReference minus_one_half =
3975 ExternalReference::address_of_minus_one_half(); 4053 ExternalReference::address_of_minus_one_half();
3976 4054
3977 Label done, round_to_zero, below_one_half, do_not_compensate; 4055 Label done, round_to_zero, below_one_half, do_not_compensate;
4056 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
4057
3978 __ movsd(xmm_scratch, Operand::StaticVariable(one_half)); 4058 __ movsd(xmm_scratch, Operand::StaticVariable(one_half));
3979 __ ucomisd(xmm_scratch, input_reg); 4059 __ ucomisd(xmm_scratch, input_reg);
3980 __ j(above, &below_one_half); 4060 __ j(above, &below_one_half, Label::kNear);
3981 4061
3982 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). 4062 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x).
3983 __ addsd(xmm_scratch, input_reg); 4063 __ addsd(xmm_scratch, input_reg);
3984 __ cvttsd2si(output_reg, Operand(xmm_scratch)); 4064 __ cvttsd2si(output_reg, Operand(xmm_scratch));
3985 // Overflow is signalled with minint. 4065 // Overflow is signalled with minint.
3986 __ cmp(output_reg, 0x80000000u); 4066 __ cmp(output_reg, 0x80000000u);
3987 __ RecordComment("D2I conversion overflow"); 4067 __ RecordComment("D2I conversion overflow");
3988 DeoptimizeIf(equal, instr->environment()); 4068 DeoptimizeIf(equal, instr->environment());
3989 __ jmp(&done); 4069 __ jmp(&done, dist);
3990 4070
3991 __ bind(&below_one_half); 4071 __ bind(&below_one_half);
3992 __ movsd(xmm_scratch, Operand::StaticVariable(minus_one_half)); 4072 __ movsd(xmm_scratch, Operand::StaticVariable(minus_one_half));
3993 __ ucomisd(xmm_scratch, input_reg); 4073 __ ucomisd(xmm_scratch, input_reg);
3994 __ j(below_equal, &round_to_zero); 4074 __ j(below_equal, &round_to_zero, Label::kNear);
3995 4075
3996 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then 4076 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then
3997 // compare and compensate. 4077 // compare and compensate.
3998 __ movsd(input_temp, input_reg); // Do not alter input_reg. 4078 __ movaps(input_temp, input_reg); // Do not alter input_reg.
3999 __ subsd(input_temp, xmm_scratch); 4079 __ subsd(input_temp, xmm_scratch);
4000 __ cvttsd2si(output_reg, Operand(input_temp)); 4080 __ cvttsd2si(output_reg, Operand(input_temp));
4001 // Catch minint due to overflow, and to prevent overflow when compensating. 4081 // Catch minint due to overflow, and to prevent overflow when compensating.
4002 __ cmp(output_reg, 0x80000000u); 4082 __ cmp(output_reg, 0x80000000u);
4003 __ RecordComment("D2I conversion overflow"); 4083 __ RecordComment("D2I conversion overflow");
4004 DeoptimizeIf(equal, instr->environment()); 4084 DeoptimizeIf(equal, instr->environment());
4005 4085
4006 __ Cvtsi2sd(xmm_scratch, output_reg); 4086 __ Cvtsi2sd(xmm_scratch, output_reg);
4007 __ ucomisd(xmm_scratch, input_temp); 4087 __ ucomisd(xmm_scratch, input_temp);
4008 __ j(equal, &done); 4088 __ j(equal, &done, dist);
4009 __ sub(output_reg, Immediate(1)); 4089 __ sub(output_reg, Immediate(1));
4010 // No overflow because we already ruled out minint. 4090 // No overflow because we already ruled out minint.
4011 __ jmp(&done); 4091 __ jmp(&done, dist);
4012 4092
4013 __ bind(&round_to_zero); 4093 __ bind(&round_to_zero);
4014 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if 4094 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if
4015 // we can ignore the difference between a result of -0 and +0. 4095 // we can ignore the difference between a result of -0 and +0.
4016 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 4096 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
4017 // If the sign is positive, we return +0. 4097 // If the sign is positive, we return +0.
4018 __ movmskpd(output_reg, input_reg); 4098 __ movmskpd(output_reg, input_reg);
4019 __ test(output_reg, Immediate(1)); 4099 __ test(output_reg, Immediate(1));
4020 __ RecordComment("Minus zero"); 4100 __ RecordComment("Minus zero");
4021 DeoptimizeIf(not_zero, instr->environment()); 4101 DeoptimizeIf(not_zero, instr->environment());
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after
4356 ArrayNoArgumentConstructorStub stub(kind, context_mode, override_mode); 4436 ArrayNoArgumentConstructorStub stub(kind, context_mode, override_mode);
4357 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); 4437 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
4358 } else if (instr->arity() == 1) { 4438 } else if (instr->arity() == 1) {
4359 Label done; 4439 Label done;
4360 if (IsFastPackedElementsKind(kind)) { 4440 if (IsFastPackedElementsKind(kind)) {
4361 Label packed_case; 4441 Label packed_case;
4362 // We might need a change here 4442 // We might need a change here
4363 // look at the first argument 4443 // look at the first argument
4364 __ mov(ecx, Operand(esp, 0)); 4444 __ mov(ecx, Operand(esp, 0));
4365 __ test(ecx, ecx); 4445 __ test(ecx, ecx);
4366 __ j(zero, &packed_case); 4446 __ j(zero, &packed_case, Label::kNear);
4367 4447
4368 ElementsKind holey_kind = GetHoleyElementsKind(kind); 4448 ElementsKind holey_kind = GetHoleyElementsKind(kind);
4369 ArraySingleArgumentConstructorStub stub(holey_kind, context_mode, 4449 ArraySingleArgumentConstructorStub stub(holey_kind, context_mode,
4370 override_mode); 4450 override_mode);
4371 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); 4451 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
4372 __ jmp(&done); 4452 __ jmp(&done, Label::kNear);
4373 __ bind(&packed_case); 4453 __ bind(&packed_case);
4374 } 4454 }
4375 4455
4376 ArraySingleArgumentConstructorStub stub(kind, context_mode, override_mode); 4456 ArraySingleArgumentConstructorStub stub(kind, context_mode, override_mode);
4377 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); 4457 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
4378 __ bind(&done); 4458 __ bind(&done);
4379 } else { 4459 } else {
4380 ArrayNArgumentsConstructorStub stub(kind, context_mode, override_mode); 4460 ArrayNArgumentsConstructorStub stub(kind, context_mode, override_mode);
4381 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); 4461 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
4382 } 4462 }
4383 } 4463 }
4384 4464
4385 4465
4386 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { 4466 void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
4467 ASSERT(ToRegister(instr->context()).is(esi));
4387 CallRuntime(instr->function(), instr->arity(), instr, instr->save_doubles()); 4468 CallRuntime(instr->function(), instr->arity(), instr, instr->save_doubles());
4388 } 4469 }
4389 4470
4390 4471
4391 void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) { 4472 void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) {
4392 Register function = ToRegister(instr->function()); 4473 Register function = ToRegister(instr->function());
4393 Register code_object = ToRegister(instr->code_object()); 4474 Register code_object = ToRegister(instr->code_object());
4394 __ lea(code_object, FieldOperand(code_object, Code::kHeaderSize)); 4475 __ lea(code_object, FieldOperand(code_object, Code::kHeaderSize));
4395 __ mov(FieldOperand(function, JSFunction::kCodeEntryOffset), code_object); 4476 __ mov(FieldOperand(function, JSFunction::kCodeEntryOffset), code_object);
4396 } 4477 }
(...skipping 12 matching lines...) Expand all
4409 HObjectAccess access = instr->hydrogen()->access(); 4490 HObjectAccess access = instr->hydrogen()->access();
4410 int offset = access.offset(); 4491 int offset = access.offset();
4411 4492
4412 if (access.IsExternalMemory()) { 4493 if (access.IsExternalMemory()) {
4413 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); 4494 ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
4414 MemOperand operand = instr->object()->IsConstantOperand() 4495 MemOperand operand = instr->object()->IsConstantOperand()
4415 ? MemOperand::StaticVariable( 4496 ? MemOperand::StaticVariable(
4416 ToExternalReference(LConstantOperand::cast(instr->object()))) 4497 ToExternalReference(LConstantOperand::cast(instr->object())))
4417 : MemOperand(ToRegister(instr->object()), offset); 4498 : MemOperand(ToRegister(instr->object()), offset);
4418 if (instr->value()->IsConstantOperand()) { 4499 if (instr->value()->IsConstantOperand()) {
4419 ASSERT(!representation.IsByte());
4420 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); 4500 LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
4421 __ mov(operand, Immediate(ToInteger32(operand_value))); 4501 __ mov(operand, Immediate(ToInteger32(operand_value)));
4422 } else { 4502 } else {
4423 Register value = ToRegister(instr->value()); 4503 Register value = ToRegister(instr->value());
4424 if (representation.IsByte()) { 4504 __ Store(value, operand, representation);
4425 __ mov_b(operand, value);
4426 } else {
4427 __ mov(operand, value);
4428 }
4429 } 4505 }
4430 return; 4506 return;
4431 } 4507 }
4432 4508
4433 Register object = ToRegister(instr->object()); 4509 Register object = ToRegister(instr->object());
4434 Handle<Map> transition = instr->transition(); 4510 Handle<Map> transition = instr->transition();
4435 4511
4436 if (FLAG_track_fields && representation.IsSmi()) { 4512 if (FLAG_track_fields && representation.IsSmi()) {
4437 if (instr->value()->IsConstantOperand()) { 4513 if (instr->value()->IsConstantOperand()) {
4438 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); 4514 LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
4496 if (!access.IsInobject()) { 4572 if (!access.IsInobject()) {
4497 write_register = ToRegister(instr->temp()); 4573 write_register = ToRegister(instr->temp());
4498 __ mov(write_register, FieldOperand(object, JSObject::kPropertiesOffset)); 4574 __ mov(write_register, FieldOperand(object, JSObject::kPropertiesOffset));
4499 } 4575 }
4500 4576
4501 MemOperand operand = FieldOperand(write_register, offset); 4577 MemOperand operand = FieldOperand(write_register, offset);
4502 if (instr->value()->IsConstantOperand()) { 4578 if (instr->value()->IsConstantOperand()) {
4503 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); 4579 LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
4504 if (operand_value->IsRegister()) { 4580 if (operand_value->IsRegister()) {
4505 Register value = ToRegister(operand_value); 4581 Register value = ToRegister(operand_value);
4506 if (representation.IsByte()) { 4582 __ Store(value, operand, representation);
4507 __ mov_b(operand, value); 4583 } else if (representation.IsInteger32()) {
4508 } else { 4584 Immediate immediate = ToImmediate(operand_value, representation);
4509 __ mov(operand, value); 4585 ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
4510 } 4586 __ mov(operand, immediate);
4511 } else { 4587 } else {
4512 Handle<Object> handle_value = ToHandle(operand_value); 4588 Handle<Object> handle_value = ToHandle(operand_value);
4513 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); 4589 ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
4514 __ mov(operand, handle_value); 4590 __ mov(operand, handle_value);
4515 } 4591 }
4516 } else { 4592 } else {
4517 Register value = ToRegister(instr->value()); 4593 Register value = ToRegister(instr->value());
4518 if (representation.IsByte()) { 4594 __ Store(value, operand, representation);
4519 __ mov_b(operand, value);
4520 } else {
4521 __ mov(operand, value);
4522 }
4523 } 4595 }
4524 4596
4525 if (instr->hydrogen()->NeedsWriteBarrier()) { 4597 if (instr->hydrogen()->NeedsWriteBarrier()) {
4526 Register value = ToRegister(instr->value()); 4598 Register value = ToRegister(instr->value());
4527 Register temp = access.IsInobject() ? ToRegister(instr->temp()) : object; 4599 Register temp = access.IsInobject() ? ToRegister(instr->temp()) : object;
4528 // Update the write barrier for the object for in-object properties. 4600 // Update the write barrier for the object for in-object properties.
4529 __ RecordWriteField(write_register, 4601 __ RecordWriteField(write_register,
4530 offset, 4602 offset,
4531 value, 4603 value,
4532 temp, 4604 temp,
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
4659 instr->additional_index()); 4731 instr->additional_index());
4660 4732
4661 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { 4733 if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
4662 CpuFeatureScope scope(masm(), SSE2); 4734 CpuFeatureScope scope(masm(), SSE2);
4663 XMMRegister value = ToDoubleRegister(instr->value()); 4735 XMMRegister value = ToDoubleRegister(instr->value());
4664 4736
4665 if (instr->NeedsCanonicalization()) { 4737 if (instr->NeedsCanonicalization()) {
4666 Label have_value; 4738 Label have_value;
4667 4739
4668 __ ucomisd(value, value); 4740 __ ucomisd(value, value);
4669 __ j(parity_odd, &have_value); // NaN. 4741 __ j(parity_odd, &have_value, Label::kNear); // NaN.
4670 4742
4671 __ movsd(value, Operand::StaticVariable(canonical_nan_reference)); 4743 __ movsd(value, Operand::StaticVariable(canonical_nan_reference));
4672 __ bind(&have_value); 4744 __ bind(&have_value);
4673 } 4745 }
4674 4746
4675 __ movsd(double_store_operand, value); 4747 __ movsd(double_store_operand, value);
4676 } else { 4748 } else {
4677 // Can't use SSE2 in the serializer 4749 // Can't use SSE2 in the serializer
4678 if (instr->hydrogen()->IsConstantHoleStore()) { 4750 if (instr->hydrogen()->IsConstantHoleStore()) {
4679 // This means we should store the (double) hole. No floating point 4751 // This means we should store the (double) hole. No floating point
(...skipping 15 matching lines...) Expand all
4695 } else { 4767 } else {
4696 Label no_special_nan_handling; 4768 Label no_special_nan_handling;
4697 X87Register value = ToX87Register(instr->value()); 4769 X87Register value = ToX87Register(instr->value());
4698 X87Fxch(value); 4770 X87Fxch(value);
4699 4771
4700 if (instr->NeedsCanonicalization()) { 4772 if (instr->NeedsCanonicalization()) {
4701 __ fld(0); 4773 __ fld(0);
4702 __ fld(0); 4774 __ fld(0);
4703 __ FCmp(); 4775 __ FCmp();
4704 4776
4705 __ j(parity_odd, &no_special_nan_handling); 4777 __ j(parity_odd, &no_special_nan_handling, Label::kNear);
4706 __ sub(esp, Immediate(kDoubleSize)); 4778 __ sub(esp, Immediate(kDoubleSize));
4707 __ fst_d(MemOperand(esp, 0)); 4779 __ fst_d(MemOperand(esp, 0));
4708 __ cmp(MemOperand(esp, sizeof(kHoleNanLower32)), 4780 __ cmp(MemOperand(esp, sizeof(kHoleNanLower32)),
4709 Immediate(kHoleNanUpper32)); 4781 Immediate(kHoleNanUpper32));
4710 __ add(esp, Immediate(kDoubleSize)); 4782 __ add(esp, Immediate(kDoubleSize));
4711 Label canonicalize; 4783 Label canonicalize;
4712 __ j(not_equal, &canonicalize); 4784 __ j(not_equal, &canonicalize, Label::kNear);
4713 __ jmp(&no_special_nan_handling); 4785 __ jmp(&no_special_nan_handling, Label::kNear);
4714 __ bind(&canonicalize); 4786 __ bind(&canonicalize);
4715 __ fstp(0); 4787 __ fstp(0);
4716 __ fld_d(Operand::StaticVariable(canonical_nan_reference)); 4788 __ fld_d(Operand::StaticVariable(canonical_nan_reference));
4717 } 4789 }
4718 4790
4719 __ bind(&no_special_nan_handling); 4791 __ bind(&no_special_nan_handling);
4720 __ fst_d(double_store_operand); 4792 __ fst_d(double_store_operand);
4721 } 4793 }
4722 } 4794 }
4723 } 4795 }
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
4950 5022
4951 PushSafepointRegistersScope scope(this); 5023 PushSafepointRegistersScope scope(this);
4952 __ SmiTag(char_code); 5024 __ SmiTag(char_code);
4953 __ push(char_code); 5025 __ push(char_code);
4954 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context()); 5026 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context());
4955 __ StoreToSafepointRegisterSlot(result, eax); 5027 __ StoreToSafepointRegisterSlot(result, eax);
4956 } 5028 }
4957 5029
4958 5030
4959 void LCodeGen::DoStringAdd(LStringAdd* instr) { 5031 void LCodeGen::DoStringAdd(LStringAdd* instr) {
4960 EmitPushTaggedOperand(instr->left()); 5032 ASSERT(ToRegister(instr->context()).is(esi));
4961 EmitPushTaggedOperand(instr->right()); 5033 if (FLAG_new_string_add) {
4962 StringAddStub stub(instr->hydrogen()->flags()); 5034 ASSERT(ToRegister(instr->left()).is(edx));
4963 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); 5035 ASSERT(ToRegister(instr->right()).is(eax));
5036 NewStringAddStub stub(instr->hydrogen()->flags(),
5037 isolate()->heap()->GetPretenureMode());
5038 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
5039 } else {
5040 EmitPushTaggedOperand(instr->left());
5041 EmitPushTaggedOperand(instr->right());
5042 StringAddStub stub(instr->hydrogen()->flags());
5043 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
5044 }
4964 } 5045 }
4965 5046
4966 5047
4967 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { 5048 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
4968 LOperand* input = instr->value(); 5049 LOperand* input = instr->value();
4969 LOperand* output = instr->result(); 5050 LOperand* output = instr->result();
4970 ASSERT(input->IsRegister() || input->IsStackSlot()); 5051 ASSERT(input->IsRegister() || input->IsStackSlot());
4971 ASSERT(output->IsDoubleRegister()); 5052 ASSERT(output->IsDoubleRegister());
4972 if (CpuFeatures::IsSupported(SSE2)) { 5053 if (CpuFeatures::IsSupported(SSE2)) {
4973 CpuFeatureScope scope(masm(), SSE2); 5054 CpuFeatureScope scope(masm(), SSE2);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
5005 ToDoubleRegister(temp)); 5086 ToDoubleRegister(temp));
5006 } else { 5087 } else {
5007 X87Register res = ToX87Register(output); 5088 X87Register res = ToX87Register(output);
5008 X87PrepareToWrite(res); 5089 X87PrepareToWrite(res);
5009 __ LoadUint32NoSSE2(ToRegister(input)); 5090 __ LoadUint32NoSSE2(ToRegister(input));
5010 X87CommitWrite(res); 5091 X87CommitWrite(res);
5011 } 5092 }
5012 } 5093 }
5013 5094
5014 5095
5096 void LCodeGen::DoUint32ToSmi(LUint32ToSmi* instr) {
5097 Register input = ToRegister(instr->value());
5098 if (!instr->hydrogen()->value()->HasRange() ||
5099 !instr->hydrogen()->value()->range()->IsInSmiRange()) {
5100 __ test(input, Immediate(0xc0000000));
5101 DeoptimizeIf(not_zero, instr->environment());
5102 }
5103 __ SmiTag(input);
5104 }
5105
5106
5015 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { 5107 void LCodeGen::DoNumberTagI(LNumberTagI* instr) {
5016 class DeferredNumberTagI V8_FINAL : public LDeferredCode { 5108 class DeferredNumberTagI V8_FINAL : public LDeferredCode {
5017 public: 5109 public:
5018 DeferredNumberTagI(LCodeGen* codegen, 5110 DeferredNumberTagI(LCodeGen* codegen,
5019 LNumberTagI* instr, 5111 LNumberTagI* instr,
5020 const X87Stack& x87_stack) 5112 const X87Stack& x87_stack)
5021 : LDeferredCode(codegen, x87_stack), instr_(instr) { } 5113 : LDeferredCode(codegen, x87_stack), instr_(instr) { }
5022 virtual void Generate() V8_OVERRIDE { 5114 virtual void Generate() V8_OVERRIDE {
5023 codegen()->DoDeferredNumberTagI(instr_, instr_->value(), SIGNED_INT32); 5115 codegen()->DoDeferredNumberTagI(instr_, instr_->value(), SIGNED_INT32);
5024 } 5116 }
(...skipping 647 matching lines...) Expand 10 before | Expand all | Expand 10 after
5672 DeferredCheckMaps* deferred = NULL; 5764 DeferredCheckMaps* deferred = NULL;
5673 if (instr->hydrogen()->has_migration_target()) { 5765 if (instr->hydrogen()->has_migration_target()) {
5674 deferred = new(zone()) DeferredCheckMaps(this, instr, reg, x87_stack_); 5766 deferred = new(zone()) DeferredCheckMaps(this, instr, reg, x87_stack_);
5675 __ bind(deferred->check_maps()); 5767 __ bind(deferred->check_maps());
5676 } 5768 }
5677 5769
5678 UniqueSet<Map> map_set = instr->hydrogen()->map_set(); 5770 UniqueSet<Map> map_set = instr->hydrogen()->map_set();
5679 Label success; 5771 Label success;
5680 for (int i = 0; i < map_set.size() - 1; i++) { 5772 for (int i = 0; i < map_set.size() - 1; i++) {
5681 Handle<Map> map = map_set.at(i).handle(); 5773 Handle<Map> map = map_set.at(i).handle();
5682 __ CompareMap(reg, map, &success); 5774 __ CompareMap(reg, map);
5683 __ j(equal, &success); 5775 __ j(equal, &success, Label::kNear);
5684 } 5776 }
5685 5777
5686 Handle<Map> map = map_set.at(map_set.size() - 1).handle(); 5778 Handle<Map> map = map_set.at(map_set.size() - 1).handle();
5687 __ CompareMap(reg, map, &success); 5779 __ CompareMap(reg, map);
5688 if (instr->hydrogen()->has_migration_target()) { 5780 if (instr->hydrogen()->has_migration_target()) {
5689 __ j(not_equal, deferred->entry()); 5781 __ j(not_equal, deferred->entry());
5690 } else { 5782 } else {
5691 DeoptimizeIf(not_equal, instr->environment()); 5783 DeoptimizeIf(not_equal, instr->environment());
5692 } 5784 }
5693 5785
5694 __ bind(&success); 5786 __ bind(&success);
5695 } 5787 }
5696 5788
5697 5789
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
5755 Register scratch2 = ToRegister(instr->scratch2()); 5847 Register scratch2 = ToRegister(instr->scratch2());
5756 Register scratch3 = ToRegister(instr->scratch3()); 5848 Register scratch3 = ToRegister(instr->scratch3());
5757 Label is_smi, done, heap_number, valid_exponent, 5849 Label is_smi, done, heap_number, valid_exponent,
5758 largest_value, zero_result, maybe_nan_or_infinity; 5850 largest_value, zero_result, maybe_nan_or_infinity;
5759 5851
5760 __ JumpIfSmi(input_reg, &is_smi); 5852 __ JumpIfSmi(input_reg, &is_smi);
5761 5853
5762 // Check for heap number 5854 // Check for heap number
5763 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 5855 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5764 factory()->heap_number_map()); 5856 factory()->heap_number_map());
5765 __ j(equal, &heap_number, Label::kFar); 5857 __ j(equal, &heap_number, Label::kNear);
5766 5858
5767 // Check for undefined. Undefined is converted to zero for clamping 5859 // Check for undefined. Undefined is converted to zero for clamping
5768 // conversions. 5860 // conversions.
5769 __ cmp(input_reg, factory()->undefined_value()); 5861 __ cmp(input_reg, factory()->undefined_value());
5770 DeoptimizeIf(not_equal, instr->environment()); 5862 DeoptimizeIf(not_equal, instr->environment());
5771 __ jmp(&zero_result); 5863 __ jmp(&zero_result, Label::kNear);
5772 5864
5773 // Heap number 5865 // Heap number
5774 __ bind(&heap_number); 5866 __ bind(&heap_number);
5775 5867
5776 // Surprisingly, all of the hand-crafted bit-manipulations below are much 5868 // Surprisingly, all of the hand-crafted bit-manipulations below are much
5777 // faster than the x86 FPU built-in instruction, especially since "banker's 5869 // faster than the x86 FPU built-in instruction, especially since "banker's
5778 // rounding" would be additionally very expensive 5870 // rounding" would be additionally very expensive
5779 5871
5780 // Get exponent word. 5872 // Get exponent word.
5781 __ mov(scratch, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 5873 __ mov(scratch, FieldOperand(input_reg, HeapNumber::kExponentOffset));
5782 __ mov(scratch3, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); 5874 __ mov(scratch3, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
5783 5875
5784 // Test for negative values --> clamp to zero 5876 // Test for negative values --> clamp to zero
5785 __ test(scratch, scratch); 5877 __ test(scratch, scratch);
5786 __ j(negative, &zero_result); 5878 __ j(negative, &zero_result, Label::kNear);
5787 5879
5788 // Get exponent alone in scratch2. 5880 // Get exponent alone in scratch2.
5789 __ mov(scratch2, scratch); 5881 __ mov(scratch2, scratch);
5790 __ and_(scratch2, HeapNumber::kExponentMask); 5882 __ and_(scratch2, HeapNumber::kExponentMask);
5791 __ shr(scratch2, HeapNumber::kExponentShift); 5883 __ shr(scratch2, HeapNumber::kExponentShift);
5792 __ j(zero, &zero_result); 5884 __ j(zero, &zero_result, Label::kNear);
5793 __ sub(scratch2, Immediate(HeapNumber::kExponentBias - 1)); 5885 __ sub(scratch2, Immediate(HeapNumber::kExponentBias - 1));
5794 __ j(negative, &zero_result); 5886 __ j(negative, &zero_result, Label::kNear);
5795 5887
5796 const uint32_t non_int8_exponent = 7; 5888 const uint32_t non_int8_exponent = 7;
5797 __ cmp(scratch2, Immediate(non_int8_exponent + 1)); 5889 __ cmp(scratch2, Immediate(non_int8_exponent + 1));
5798 // If the exponent is too big, check for special values. 5890 // If the exponent is too big, check for special values.
5799 __ j(greater, &maybe_nan_or_infinity, Label::kNear); 5891 __ j(greater, &maybe_nan_or_infinity, Label::kNear);
5800 5892
5801 __ bind(&valid_exponent); 5893 __ bind(&valid_exponent);
5802 // Exponent word in scratch, exponent in scratch2. We know that 0 <= exponent 5894 // Exponent word in scratch, exponent in scratch2. We know that 0 <= exponent
5803 // < 7. The shift bias is the number of bits to shift the mantissa such that 5895 // < 7. The shift bias is the number of bits to shift the mantissa such that
5804 // with an exponent of 7 such the that top-most one is in bit 30, allowing 5896 // with an exponent of 7 such the that top-most one is in bit 30, allowing
(...skipping 10 matching lines...) Expand all
5815 __ shl_cl(scratch); 5907 __ shl_cl(scratch);
5816 // Use "banker's rounding" to spec: If fractional part of number is 0.5, then 5908 // Use "banker's rounding" to spec: If fractional part of number is 0.5, then
5817 // use the bit in the "ones" place and add it to the "halves" place, which has 5909 // use the bit in the "ones" place and add it to the "halves" place, which has
5818 // the effect of rounding to even. 5910 // the effect of rounding to even.
5819 __ mov(scratch2, scratch); 5911 __ mov(scratch2, scratch);
5820 const uint32_t one_half_bit_shift = 30 - sizeof(uint8_t) * 8; 5912 const uint32_t one_half_bit_shift = 30 - sizeof(uint8_t) * 8;
5821 const uint32_t one_bit_shift = one_half_bit_shift + 1; 5913 const uint32_t one_bit_shift = one_half_bit_shift + 1;
5822 __ and_(scratch2, Immediate((1 << one_bit_shift) - 1)); 5914 __ and_(scratch2, Immediate((1 << one_bit_shift) - 1));
5823 __ cmp(scratch2, Immediate(1 << one_half_bit_shift)); 5915 __ cmp(scratch2, Immediate(1 << one_half_bit_shift));
5824 Label no_round; 5916 Label no_round;
5825 __ j(less, &no_round); 5917 __ j(less, &no_round, Label::kNear);
5826 Label round_up; 5918 Label round_up;
5827 __ mov(scratch2, Immediate(1 << one_half_bit_shift)); 5919 __ mov(scratch2, Immediate(1 << one_half_bit_shift));
5828 __ j(greater, &round_up); 5920 __ j(greater, &round_up, Label::kNear);
5829 __ test(scratch3, scratch3); 5921 __ test(scratch3, scratch3);
5830 __ j(not_zero, &round_up); 5922 __ j(not_zero, &round_up, Label::kNear);
5831 __ mov(scratch2, scratch); 5923 __ mov(scratch2, scratch);
5832 __ and_(scratch2, Immediate(1 << one_bit_shift)); 5924 __ and_(scratch2, Immediate(1 << one_bit_shift));
5833 __ shr(scratch2, 1); 5925 __ shr(scratch2, 1);
5834 __ bind(&round_up); 5926 __ bind(&round_up);
5835 __ add(scratch, scratch2); 5927 __ add(scratch, scratch2);
5836 __ j(overflow, &largest_value); 5928 __ j(overflow, &largest_value, Label::kNear);
5837 __ bind(&no_round); 5929 __ bind(&no_round);
5838 __ shr(scratch, 23); 5930 __ shr(scratch, 23);
5839 __ mov(result_reg, scratch); 5931 __ mov(result_reg, scratch);
5840 __ jmp(&done, Label::kNear); 5932 __ jmp(&done, Label::kNear);
5841 5933
5842 __ bind(&maybe_nan_or_infinity); 5934 __ bind(&maybe_nan_or_infinity);
5843 // Check for NaN/Infinity, all other values map to 255 5935 // Check for NaN/Infinity, all other values map to 255
5844 __ cmp(scratch2, Immediate(HeapNumber::kInfinityOrNanExponent + 1)); 5936 __ cmp(scratch2, Immediate(HeapNumber::kInfinityOrNanExponent + 1));
5845 __ j(not_equal, &largest_value, Label::kNear); 5937 __ j(not_equal, &largest_value, Label::kNear);
5846 5938
5847 // Check for NaN, which differs from Infinity in that at least one mantissa 5939 // Check for NaN, which differs from Infinity in that at least one mantissa
5848 // bit is set. 5940 // bit is set.
5849 __ and_(scratch, HeapNumber::kMantissaMask); 5941 __ and_(scratch, HeapNumber::kMantissaMask);
5850 __ or_(scratch, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); 5942 __ or_(scratch, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
5851 __ j(not_zero, &zero_result); // M!=0 --> NaN 5943 __ j(not_zero, &zero_result, Label::kNear); // M!=0 --> NaN
5852 // Infinity -> Fall through to map to 255. 5944 // Infinity -> Fall through to map to 255.
5853 5945
5854 __ bind(&largest_value); 5946 __ bind(&largest_value);
5855 __ mov(result_reg, Immediate(255)); 5947 __ mov(result_reg, Immediate(255));
5856 __ jmp(&done, Label::kNear); 5948 __ jmp(&done, Label::kNear);
5857 5949
5858 __ bind(&zero_result); 5950 __ bind(&zero_result);
5859 __ xor_(result_reg, result_reg); 5951 __ xor_(result_reg, result_reg);
5860 __ jmp(&done); 5952 __ jmp(&done, Label::kNear);
5861 5953
5862 // smi 5954 // smi
5863 __ bind(&is_smi); 5955 __ bind(&is_smi);
5864 if (!input_reg.is(result_reg)) { 5956 if (!input_reg.is(result_reg)) {
5865 __ mov(result_reg, input_reg); 5957 __ mov(result_reg, input_reg);
5866 } 5958 }
5867 __ SmiUntag(result_reg); 5959 __ SmiUntag(result_reg);
5868 __ ClampUint8(result_reg); 5960 __ ClampUint8(result_reg);
5869 __ bind(&done); 5961 __ bind(&done);
5870 } 5962 }
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
5998 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); 6090 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index())));
5999 __ push(Immediate(instr->hydrogen()->pattern())); 6091 __ push(Immediate(instr->hydrogen()->pattern()));
6000 __ push(Immediate(instr->hydrogen()->flags())); 6092 __ push(Immediate(instr->hydrogen()->flags()));
6001 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); 6093 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr);
6002 __ mov(ebx, eax); 6094 __ mov(ebx, eax);
6003 6095
6004 __ bind(&materialized); 6096 __ bind(&materialized);
6005 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; 6097 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
6006 Label allocated, runtime_allocate; 6098 Label allocated, runtime_allocate;
6007 __ Allocate(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT); 6099 __ Allocate(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT);
6008 __ jmp(&allocated); 6100 __ jmp(&allocated, Label::kNear);
6009 6101
6010 __ bind(&runtime_allocate); 6102 __ bind(&runtime_allocate);
6011 __ push(ebx); 6103 __ push(ebx);
6012 __ push(Immediate(Smi::FromInt(size))); 6104 __ push(Immediate(Smi::FromInt(size)));
6013 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); 6105 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
6014 __ pop(ebx); 6106 __ pop(ebx);
6015 6107
6016 __ bind(&allocated); 6108 __ bind(&allocated);
6017 // Copy the content into the newly allocated memory. 6109 // Copy the content into the newly allocated memory.
6018 // (Unroll copy loop once for better throughput). 6110 // (Unroll copy loop once for better throughput).
(...skipping 24 matching lines...) Expand all
6043 __ push(esi); 6135 __ push(esi);
6044 __ push(Immediate(instr->hydrogen()->shared_info())); 6136 __ push(Immediate(instr->hydrogen()->shared_info()));
6045 __ push(Immediate(pretenure ? factory()->true_value() 6137 __ push(Immediate(pretenure ? factory()->true_value()
6046 : factory()->false_value())); 6138 : factory()->false_value()));
6047 CallRuntime(Runtime::kNewClosure, 3, instr); 6139 CallRuntime(Runtime::kNewClosure, 3, instr);
6048 } 6140 }
6049 } 6141 }
6050 6142
6051 6143
6052 void LCodeGen::DoTypeof(LTypeof* instr) { 6144 void LCodeGen::DoTypeof(LTypeof* instr) {
6145 ASSERT(ToRegister(instr->context()).is(esi));
6053 LOperand* input = instr->value(); 6146 LOperand* input = instr->value();
6054 EmitPushTaggedOperand(input); 6147 EmitPushTaggedOperand(input);
6055 CallRuntime(Runtime::kTypeof, 1, instr); 6148 CallRuntime(Runtime::kTypeof, 1, instr);
6056 } 6149 }
6057 6150
6058 6151
6059 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { 6152 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
6060 Register input = ToRegister(instr->value()); 6153 Register input = ToRegister(instr->value());
6061 6154
6062 Condition final_branch_condition = 6155 Condition final_branch_condition =
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
6198 // now identical. When LAZY is eventually completely folded into EAGER, remove 6291 // now identical. When LAZY is eventually completely folded into EAGER, remove
6199 // the special case below. 6292 // the special case below.
6200 if (info()->IsStub() && type == Deoptimizer::EAGER) { 6293 if (info()->IsStub() && type == Deoptimizer::EAGER) {
6201 type = Deoptimizer::LAZY; 6294 type = Deoptimizer::LAZY;
6202 } 6295 }
6203 Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); 6296 Comment(";;; deoptimize: %s", instr->hydrogen()->reason());
6204 DeoptimizeIf(no_condition, instr->environment(), type); 6297 DeoptimizeIf(no_condition, instr->environment(), type);
6205 } 6298 }
6206 6299
6207 6300
6301 void LCodeGen::DoDummy(LDummy* instr) {
6302 // Nothing to see here, move on!
6303 }
6304
6305
6208 void LCodeGen::DoDummyUse(LDummyUse* instr) { 6306 void LCodeGen::DoDummyUse(LDummyUse* instr) {
6209 // Nothing to see here, move on! 6307 // Nothing to see here, move on!
6210 } 6308 }
6211 6309
6212 6310
6213 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { 6311 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
6214 PushSafepointRegistersScope scope(this); 6312 PushSafepointRegistersScope scope(this);
6215 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 6313 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
6216 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); 6314 __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
6217 RecordSafepointWithLazyDeopt( 6315 RecordSafepointWithLazyDeopt(
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
6287 // If the environment were already registered, we would have no way of 6385 // If the environment were already registered, we would have no way of
6288 // backpatching it with the spill slot operands. 6386 // backpatching it with the spill slot operands.
6289 ASSERT(!environment->HasBeenRegistered()); 6387 ASSERT(!environment->HasBeenRegistered());
6290 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 6388 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
6291 6389
6292 GenerateOsrPrologue(); 6390 GenerateOsrPrologue();
6293 } 6391 }
6294 6392
6295 6393
6296 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { 6394 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
6395 ASSERT(ToRegister(instr->context()).is(esi));
6297 __ cmp(eax, isolate()->factory()->undefined_value()); 6396 __ cmp(eax, isolate()->factory()->undefined_value());
6298 DeoptimizeIf(equal, instr->environment()); 6397 DeoptimizeIf(equal, instr->environment());
6299 6398
6300 __ cmp(eax, isolate()->factory()->null_value()); 6399 __ cmp(eax, isolate()->factory()->null_value());
6301 DeoptimizeIf(equal, instr->environment()); 6400 DeoptimizeIf(equal, instr->environment());
6302 6401
6303 __ test(eax, Immediate(kSmiTagMask)); 6402 __ test(eax, Immediate(kSmiTagMask));
6304 DeoptimizeIf(zero, instr->environment()); 6403 DeoptimizeIf(zero, instr->environment());
6305 6404
6306 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 6405 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
(...skipping 17 matching lines...) Expand all
6324 __ bind(&use_cache); 6423 __ bind(&use_cache);
6325 } 6424 }
6326 6425
6327 6426
6328 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { 6427 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
6329 Register map = ToRegister(instr->map()); 6428 Register map = ToRegister(instr->map());
6330 Register result = ToRegister(instr->result()); 6429 Register result = ToRegister(instr->result());
6331 Label load_cache, done; 6430 Label load_cache, done;
6332 __ EnumLength(result, map); 6431 __ EnumLength(result, map);
6333 __ cmp(result, Immediate(Smi::FromInt(0))); 6432 __ cmp(result, Immediate(Smi::FromInt(0)));
6334 __ j(not_equal, &load_cache); 6433 __ j(not_equal, &load_cache, Label::kNear);
6335 __ mov(result, isolate()->factory()->empty_fixed_array()); 6434 __ mov(result, isolate()->factory()->empty_fixed_array());
6336 __ jmp(&done); 6435 __ jmp(&done, Label::kNear);
6337 6436
6338 __ bind(&load_cache); 6437 __ bind(&load_cache);
6339 __ LoadInstanceDescriptors(map, result); 6438 __ LoadInstanceDescriptors(map, result);
6340 __ mov(result, 6439 __ mov(result,
6341 FieldOperand(result, DescriptorArray::kEnumCacheOffset)); 6440 FieldOperand(result, DescriptorArray::kEnumCacheOffset));
6342 __ mov(result, 6441 __ mov(result,
6343 FieldOperand(result, FixedArray::SizeFor(instr->idx()))); 6442 FieldOperand(result, FixedArray::SizeFor(instr->idx())));
6344 __ bind(&done); 6443 __ bind(&done);
6345 __ test(result, result); 6444 __ test(result, result);
6346 DeoptimizeIf(equal, instr->environment()); 6445 DeoptimizeIf(equal, instr->environment());
6347 } 6446 }
6348 6447
6349 6448
6350 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { 6449 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
6351 Register object = ToRegister(instr->value()); 6450 Register object = ToRegister(instr->value());
6352 __ cmp(ToRegister(instr->map()), 6451 __ cmp(ToRegister(instr->map()),
6353 FieldOperand(object, HeapObject::kMapOffset)); 6452 FieldOperand(object, HeapObject::kMapOffset));
6354 DeoptimizeIf(not_equal, instr->environment()); 6453 DeoptimizeIf(not_equal, instr->environment());
6355 } 6454 }
6356 6455
6357 6456
6358 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) { 6457 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) {
6359 Register object = ToRegister(instr->object()); 6458 Register object = ToRegister(instr->object());
6360 Register index = ToRegister(instr->index()); 6459 Register index = ToRegister(instr->index());
6361 6460
6362 Label out_of_object, done; 6461 Label out_of_object, done;
6363 __ cmp(index, Immediate(0)); 6462 __ cmp(index, Immediate(0));
6364 __ j(less, &out_of_object); 6463 __ j(less, &out_of_object, Label::kNear);
6365 __ mov(object, FieldOperand(object, 6464 __ mov(object, FieldOperand(object,
6366 index, 6465 index,
6367 times_half_pointer_size, 6466 times_half_pointer_size,
6368 JSObject::kHeaderSize)); 6467 JSObject::kHeaderSize));
6369 __ jmp(&done, Label::kNear); 6468 __ jmp(&done, Label::kNear);
6370 6469
6371 __ bind(&out_of_object); 6470 __ bind(&out_of_object);
6372 __ mov(object, FieldOperand(object, JSObject::kPropertiesOffset)); 6471 __ mov(object, FieldOperand(object, JSObject::kPropertiesOffset));
6373 __ neg(index); 6472 __ neg(index);
6374 // Index is now equal to out of object property index plus 1. 6473 // Index is now equal to out of object property index plus 1.
6375 __ mov(object, FieldOperand(object, 6474 __ mov(object, FieldOperand(object,
6376 index, 6475 index,
6377 times_half_pointer_size, 6476 times_half_pointer_size,
6378 FixedArray::kHeaderSize - kPointerSize)); 6477 FixedArray::kHeaderSize - kPointerSize));
6379 __ bind(&done); 6478 __ bind(&done);
6380 } 6479 }
6381 6480
6382 6481
6383 #undef __ 6482 #undef __
6384 6483
6385 } } // namespace v8::internal 6484 } } // namespace v8::internal
6386 6485
6387 #endif // V8_TARGET_ARCH_IA32 6486 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-gap-resolver-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698