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

Side by Side Diff: src/builtins/builtins-number.cc

Issue 2517833005: [cleanup] Refactor builtins-number.cc (Closed)
Patch Set: ready for review Created 4 years 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
« no previous file with comments | « no previous file | src/builtins/builtins-utils.h » ('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 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/builtins/builtins-utils.h" 5 #include "src/builtins/builtins-utils.h"
6 #include "src/builtins/builtins.h" 6 #include "src/builtins/builtins.h"
7 #include "src/code-factory.h" 7 #include "src/code-factory.h"
8 #include "src/code-stub-assembler.h"
8 9
9 namespace v8 { 10 namespace v8 {
10 namespace internal { 11 namespace internal {
11 12
13 class NumberBuiltinsAssembler : public CodeStubAssembler {
14 public:
15 explicit NumberBuiltinsAssembler(compiler::CodeAssemblerState* state)
16 : CodeStubAssembler(state) {}
17
18 protected:
19 template <Signedness signed_result = kSigned>
20 void BitwiseOp(std::function<Node*(Node* lhs, Node* rhs)> body) {
21 Node* left = Parameter(0);
22 Node* right = Parameter(1);
23 Node* context = Parameter(2);
24
25 Node* lhs_value = TruncateTaggedToWord32(context, left);
26 Node* rhs_value = TruncateTaggedToWord32(context, right);
27 Node* value = body(lhs_value, rhs_value);
28 Node* result = signed_result == kSigned ? ChangeInt32ToTagged(value)
29 : ChangeUint32ToTagged(value);
30 Return(result);
31 }
32
33 template <Signedness signed_result = kSigned>
34 void BitwiseShiftOp(std::function<Node*(Node* lhs, Node* shift_count)> body) {
35 BitwiseOp<signed_result>([this, body](Node* lhs, Node* rhs) {
36 Node* shift_count = Word32And(rhs, Int32Constant(0x1f));
37 return body(lhs, shift_count);
38 });
39 }
40
41 void RelationalComparisonBuiltin(RelationalComparisonMode mode) {
42 Node* lhs = Parameter(0);
43 Node* rhs = Parameter(1);
44 Node* context = Parameter(2);
45
46 Return(RelationalComparison(mode, lhs, rhs, context));
47 }
48 };
49
12 // ----------------------------------------------------------------------------- 50 // -----------------------------------------------------------------------------
13 // ES6 section 20.1 Number Objects 51 // ES6 section 20.1 Number Objects
14 52
15 // ES6 section 20.1.2.2 Number.isFinite ( number ) 53 // ES6 section 20.1.2.2 Number.isFinite ( number )
16 void Builtins::Generate_NumberIsFinite(compiler::CodeAssemblerState* state) { 54 TF_BUILTIN(NumberIsFinite, CodeStubAssembler) {
17 typedef CodeStubAssembler::Label Label; 55 Node* number = Parameter(1);
18 typedef compiler::Node Node; 56
19 CodeStubAssembler assembler(state); 57 Label return_true(this), return_false(this);
20 58
21 Node* number = assembler.Parameter(1); 59 // Check if {number} is a Smi.
22 60 GotoIf(TaggedIsSmi(number), &return_true);
23 Label return_true(&assembler), return_false(&assembler); 61
24 62 // Check if {number} is a HeapNumber.
25 // Check if {number} is a Smi. 63 GotoUnless(IsHeapNumberMap(LoadMap(number)), &return_false);
26 assembler.GotoIf(assembler.TaggedIsSmi(number), &return_true);
27
28 // Check if {number} is a HeapNumber.
29 assembler.GotoUnless(assembler.WordEqual(assembler.LoadMap(number),
30 assembler.HeapNumberMapConstant()),
31 &return_false);
32 64
33 // Check if {number} contains a finite, non-NaN value. 65 // Check if {number} contains a finite, non-NaN value.
34 Node* number_value = assembler.LoadHeapNumberValue(number); 66 Node* number_value = LoadHeapNumberValue(number);
35 assembler.BranchIfFloat64IsNaN( 67 BranchIfFloat64IsNaN(Float64Sub(number_value, number_value), &return_false,
36 assembler.Float64Sub(number_value, number_value), &return_false, 68 &return_true);
37 &return_true); 69
38 70 Bind(&return_true);
39 assembler.Bind(&return_true); 71 Return(BooleanConstant(true));
40 assembler.Return(assembler.BooleanConstant(true)); 72
41 73 Bind(&return_false);
42 assembler.Bind(&return_false); 74 Return(BooleanConstant(false));
43 assembler.Return(assembler.BooleanConstant(false));
44 } 75 }
45 76
46 // ES6 section 20.1.2.3 Number.isInteger ( number ) 77 // ES6 section 20.1.2.3 Number.isInteger ( number )
47 void Builtins::Generate_NumberIsInteger(compiler::CodeAssemblerState* state) { 78 TF_BUILTIN(NumberIsInteger, CodeStubAssembler) {
48 typedef CodeStubAssembler::Label Label; 79 Node* number = Parameter(1);
49 typedef compiler::Node Node; 80
50 CodeStubAssembler assembler(state); 81 Label return_true(this), return_false(this);
51 82
52 Node* number = assembler.Parameter(1); 83 // Check if {number} is a Smi.
53 84 GotoIf(TaggedIsSmi(number), &return_true);
54 Label return_true(&assembler), return_false(&assembler); 85
55 86 // Check if {number} is a HeapNumber.
56 // Check if {number} is a Smi. 87 GotoUnless(IsHeapNumberMap(LoadMap(number)), &return_false);
57 assembler.GotoIf(assembler.TaggedIsSmi(number), &return_true);
58
59 // Check if {number} is a HeapNumber.
60 assembler.GotoUnless(assembler.WordEqual(assembler.LoadMap(number),
61 assembler.HeapNumberMapConstant()),
62 &return_false);
63 88
64 // Load the actual value of {number}. 89 // Load the actual value of {number}.
65 Node* number_value = assembler.LoadHeapNumberValue(number); 90 Node* number_value = LoadHeapNumberValue(number);
66 91
67 // Truncate the value of {number} to an integer (or an infinity). 92 // Truncate the value of {number} to an integer (or an infinity).
68 Node* integer = assembler.Float64Trunc(number_value); 93 Node* integer = Float64Trunc(number_value);
69 94
70 // Check if {number}s value matches the integer (ruling out the infinities). 95 // Check if {number}s value matches the integer (ruling out the infinities).
71 assembler.Branch( 96 Branch(Float64Equal(Float64Sub(number_value, integer), Float64Constant(0.0)),
72 assembler.Float64Equal(assembler.Float64Sub(number_value, integer), 97 &return_true, &return_false);
73 assembler.Float64Constant(0.0)), 98
74 &return_true, &return_false); 99 Bind(&return_true);
75 100 Return(BooleanConstant(true));
76 assembler.Bind(&return_true); 101
77 assembler.Return(assembler.BooleanConstant(true)); 102 Bind(&return_false);
78 103 Return(BooleanConstant(false));
79 assembler.Bind(&return_false);
80 assembler.Return(assembler.BooleanConstant(false));
81 } 104 }
82 105
83 // ES6 section 20.1.2.4 Number.isNaN ( number ) 106 // ES6 section 20.1.2.4 Number.isNaN ( number )
84 void Builtins::Generate_NumberIsNaN(compiler::CodeAssemblerState* state) { 107 TF_BUILTIN(NumberIsNaN, CodeStubAssembler) {
85 typedef CodeStubAssembler::Label Label; 108 Node* number = Parameter(1);
86 typedef compiler::Node Node; 109
87 CodeStubAssembler assembler(state); 110 Label return_true(this), return_false(this);
88 111
89 Node* number = assembler.Parameter(1); 112 // Check if {number} is a Smi.
90 113 GotoIf(TaggedIsSmi(number), &return_false);
91 Label return_true(&assembler), return_false(&assembler); 114
92 115 // Check if {number} is a HeapNumber.
93 // Check if {number} is a Smi. 116 GotoUnless(IsHeapNumberMap(LoadMap(number)), &return_false);
94 assembler.GotoIf(assembler.TaggedIsSmi(number), &return_false);
95
96 // Check if {number} is a HeapNumber.
97 assembler.GotoUnless(assembler.WordEqual(assembler.LoadMap(number),
98 assembler.HeapNumberMapConstant()),
99 &return_false);
100 117
101 // Check if {number} contains a NaN value. 118 // Check if {number} contains a NaN value.
102 Node* number_value = assembler.LoadHeapNumberValue(number); 119 Node* number_value = LoadHeapNumberValue(number);
103 assembler.BranchIfFloat64IsNaN(number_value, &return_true, &return_false); 120 BranchIfFloat64IsNaN(number_value, &return_true, &return_false);
104 121
105 assembler.Bind(&return_true); 122 Bind(&return_true);
106 assembler.Return(assembler.BooleanConstant(true)); 123 Return(BooleanConstant(true));
107 124
108 assembler.Bind(&return_false); 125 Bind(&return_false);
109 assembler.Return(assembler.BooleanConstant(false)); 126 Return(BooleanConstant(false));
110 } 127 }
111 128
112 // ES6 section 20.1.2.5 Number.isSafeInteger ( number ) 129 // ES6 section 20.1.2.5 Number.isSafeInteger ( number )
113 void Builtins::Generate_NumberIsSafeInteger( 130 TF_BUILTIN(NumberIsSafeInteger, CodeStubAssembler) {
114 compiler::CodeAssemblerState* state) { 131 Node* number = Parameter(1);
115 typedef CodeStubAssembler::Label Label; 132
116 typedef compiler::Node Node; 133 Label return_true(this), return_false(this);
117 CodeStubAssembler assembler(state); 134
118 135 // Check if {number} is a Smi.
119 Node* number = assembler.Parameter(1); 136 GotoIf(TaggedIsSmi(number), &return_true);
120 137
121 Label return_true(&assembler), return_false(&assembler); 138 // Check if {number} is a HeapNumber.
122 139 GotoUnless(IsHeapNumberMap(LoadMap(number)), &return_false);
123 // Check if {number} is a Smi.
124 assembler.GotoIf(assembler.TaggedIsSmi(number), &return_true);
125
126 // Check if {number} is a HeapNumber.
127 assembler.GotoUnless(assembler.WordEqual(assembler.LoadMap(number),
128 assembler.HeapNumberMapConstant()),
129 &return_false);
130 140
131 // Load the actual value of {number}. 141 // Load the actual value of {number}.
132 Node* number_value = assembler.LoadHeapNumberValue(number); 142 Node* number_value = LoadHeapNumberValue(number);
133 143
134 // Truncate the value of {number} to an integer (or an infinity). 144 // Truncate the value of {number} to an integer (or an infinity).
135 Node* integer = assembler.Float64Trunc(number_value); 145 Node* integer = Float64Trunc(number_value);
136 146
137 // Check if {number}s value matches the integer (ruling out the infinities). 147 // Check if {number}s value matches the integer (ruling out the infinities).
138 assembler.GotoUnless( 148 GotoUnless(
139 assembler.Float64Equal(assembler.Float64Sub(number_value, integer), 149 Float64Equal(Float64Sub(number_value, integer), Float64Constant(0.0)),
140 assembler.Float64Constant(0.0)),
141 &return_false); 150 &return_false);
142 151
143 // Check if the {integer} value is in safe integer range. 152 // Check if the {integer} value is in safe integer range.
144 assembler.Branch(assembler.Float64LessThanOrEqual( 153 Branch(Float64LessThanOrEqual(Float64Abs(integer),
145 assembler.Float64Abs(integer), 154 Float64Constant(kMaxSafeInteger)),
146 assembler.Float64Constant(kMaxSafeInteger)), 155 &return_true, &return_false);
147 &return_true, &return_false); 156
148 157 Bind(&return_true);
149 assembler.Bind(&return_true); 158 Return(BooleanConstant(true));
150 assembler.Return(assembler.BooleanConstant(true)); 159
151 160 Bind(&return_false);
152 assembler.Bind(&return_false); 161 Return(BooleanConstant(false));
153 assembler.Return(assembler.BooleanConstant(false));
154 } 162 }
155 163
156 // ES6 section 20.1.2.12 Number.parseFloat ( string ) 164 // ES6 section 20.1.2.12 Number.parseFloat ( string )
157 void Builtins::Generate_NumberParseFloat(compiler::CodeAssemblerState* state) { 165 TF_BUILTIN(NumberParseFloat, CodeStubAssembler) {
158 typedef CodeStubAssembler::Label Label; 166 Node* context = Parameter(4);
159 typedef compiler::Node Node;
160 typedef CodeStubAssembler::Variable Variable;
161 CodeStubAssembler assembler(state);
162
163 Node* context = assembler.Parameter(4);
164 167
165 // We might need to loop once for ToString conversion. 168 // We might need to loop once for ToString conversion.
166 Variable var_input(&assembler, MachineRepresentation::kTagged); 169 Variable var_input(this, MachineRepresentation::kTagged);
167 Label loop(&assembler, &var_input); 170 Label loop(this, &var_input);
168 var_input.Bind(assembler.Parameter(1)); 171 var_input.Bind(Parameter(1));
169 assembler.Goto(&loop); 172 Goto(&loop);
170 assembler.Bind(&loop); 173 Bind(&loop);
171 { 174 {
172 // Load the current {input} value. 175 // Load the current {input} value.
173 Node* input = var_input.value(); 176 Node* input = var_input.value();
174 177
175 // Check if the {input} is a HeapObject or a Smi. 178 // Check if the {input} is a HeapObject or a Smi.
176 Label if_inputissmi(&assembler), if_inputisnotsmi(&assembler); 179 Label if_inputissmi(this), if_inputisnotsmi(this);
177 assembler.Branch(assembler.TaggedIsSmi(input), &if_inputissmi, 180 Branch(TaggedIsSmi(input), &if_inputissmi, &if_inputisnotsmi);
178 &if_inputisnotsmi); 181
179 182 Bind(&if_inputissmi);
180 assembler.Bind(&if_inputissmi);
181 { 183 {
182 // The {input} is already a Number, no need to do anything. 184 // The {input} is already a Number, no need to do anything.
183 assembler.Return(input); 185 Return(input);
184 } 186 }
185 187
186 assembler.Bind(&if_inputisnotsmi); 188 Bind(&if_inputisnotsmi);
187 { 189 {
188 // The {input} is a HeapObject, check if it's already a String. 190 // The {input} is a HeapObject, check if it's already a String.
189 Label if_inputisstring(&assembler), if_inputisnotstring(&assembler); 191 Label if_inputisstring(this), if_inputisnotstring(this);
190 Node* input_map = assembler.LoadMap(input); 192 Node* input_map = LoadMap(input);
191 Node* input_instance_type = assembler.LoadMapInstanceType(input_map); 193 Node* input_instance_type = LoadMapInstanceType(input_map);
192 assembler.Branch(assembler.IsStringInstanceType(input_instance_type), 194 Branch(IsStringInstanceType(input_instance_type), &if_inputisstring,
193 &if_inputisstring, &if_inputisnotstring); 195 &if_inputisnotstring);
194 196
195 assembler.Bind(&if_inputisstring); 197 Bind(&if_inputisstring);
196 { 198 {
197 // The {input} is already a String, check if {input} contains 199 // The {input} is already a String, check if {input} contains
198 // a cached array index. 200 // a cached array index.
199 Label if_inputcached(&assembler), if_inputnotcached(&assembler); 201 Label if_inputcached(this), if_inputnotcached(this);
200 Node* input_hash = assembler.LoadNameHashField(input); 202 Node* input_hash = LoadNameHashField(input);
201 Node* input_bit = assembler.Word32And( 203 Node* input_bit = Word32And(
202 input_hash, 204 input_hash, Int32Constant(String::kContainsCachedArrayIndexMask));
203 assembler.Int32Constant(String::kContainsCachedArrayIndexMask)); 205 Branch(Word32Equal(input_bit, Int32Constant(0)), &if_inputcached,
204 assembler.Branch( 206 &if_inputnotcached);
205 assembler.Word32Equal(input_bit, assembler.Int32Constant(0)), 207
206 &if_inputcached, &if_inputnotcached); 208 Bind(&if_inputcached);
207
208 assembler.Bind(&if_inputcached);
209 { 209 {
210 // Just return the {input}s cached array index. 210 // Just return the {input}s cached array index.
211 Node* input_array_index = 211 Node* input_array_index =
212 assembler.DecodeWordFromWord32<String::ArrayIndexValueBits>( 212 DecodeWordFromWord32<String::ArrayIndexValueBits>(input_hash);
213 input_hash); 213 Return(SmiTag(input_array_index));
214 assembler.Return(assembler.SmiTag(input_array_index)); 214 }
215 } 215
216 216 Bind(&if_inputnotcached);
217 assembler.Bind(&if_inputnotcached);
218 { 217 {
219 // Need to fall back to the runtime to convert {input} to double. 218 // Need to fall back to the runtime to convert {input} to double.
220 assembler.Return(assembler.CallRuntime(Runtime::kStringParseFloat, 219 Return(CallRuntime(Runtime::kStringParseFloat, context, input));
221 context, input));
222 } 220 }
223 } 221 }
224 222
225 assembler.Bind(&if_inputisnotstring); 223 Bind(&if_inputisnotstring);
226 { 224 {
227 // The {input} is neither a String nor a Smi, check for HeapNumber. 225 // The {input} is neither a String nor a Smi, check for HeapNumber.
228 Label if_inputisnumber(&assembler), 226 Label if_inputisnumber(this),
229 if_inputisnotnumber(&assembler, Label::kDeferred); 227 if_inputisnotnumber(this, Label::kDeferred);
230 assembler.Branch( 228 Branch(IsHeapNumberMap(input_map), &if_inputisnumber,
231 assembler.WordEqual(input_map, assembler.HeapNumberMapConstant()), 229 &if_inputisnotnumber);
232 &if_inputisnumber, &if_inputisnotnumber); 230
233 231 Bind(&if_inputisnumber);
234 assembler.Bind(&if_inputisnumber);
235 { 232 {
236 // The {input} is already a Number, take care of -0. 233 // The {input} is already a Number, take care of -0.
237 Label if_inputiszero(&assembler), if_inputisnotzero(&assembler); 234 Label if_inputiszero(this), if_inputisnotzero(this);
238 Node* input_value = assembler.LoadHeapNumberValue(input); 235 Node* input_value = LoadHeapNumberValue(input);
239 assembler.Branch(assembler.Float64Equal( 236 Branch(Float64Equal(input_value, Float64Constant(0.0)),
240 input_value, assembler.Float64Constant(0.0)), 237 &if_inputiszero, &if_inputisnotzero);
241 &if_inputiszero, &if_inputisnotzero); 238
242 239 Bind(&if_inputiszero);
243 assembler.Bind(&if_inputiszero); 240 Return(SmiConstant(0));
244 assembler.Return(assembler.SmiConstant(0)); 241
245 242 Bind(&if_inputisnotzero);
246 assembler.Bind(&if_inputisnotzero); 243 Return(input);
247 assembler.Return(input); 244 }
248 } 245
249 246 Bind(&if_inputisnotnumber);
250 assembler.Bind(&if_inputisnotnumber);
251 { 247 {
252 // Need to convert the {input} to String first. 248 // Need to convert the {input} to String first.
253 // TODO(bmeurer): This could be more efficient if necessary. 249 // TODO(bmeurer): This could be more efficient if necessary.
254 Callable callable = CodeFactory::ToString(assembler.isolate()); 250 Callable callable = CodeFactory::ToString(isolate());
255 var_input.Bind(assembler.CallStub(callable, context, input)); 251 var_input.Bind(CallStub(callable, context, input));
256 assembler.Goto(&loop); 252 Goto(&loop);
257 } 253 }
258 } 254 }
259 } 255 }
260 } 256 }
261 } 257 }
262 258
263 // ES6 section 20.1.2.13 Number.parseInt ( string, radix ) 259 // ES6 section 20.1.2.13 Number.parseInt ( string, radix )
264 void Builtins::Generate_NumberParseInt(compiler::CodeAssemblerState* state) { 260 TF_BUILTIN(NumberParseInt, CodeStubAssembler) {
265 typedef CodeStubAssembler::Label Label; 261 Node* input = Parameter(1);
266 typedef compiler::Node Node; 262 Node* radix = Parameter(2);
267 CodeStubAssembler assembler(state); 263 Node* context = Parameter(5);
268
269 Node* input = assembler.Parameter(1);
270 Node* radix = assembler.Parameter(2);
271 Node* context = assembler.Parameter(5);
272 264
273 // Check if {radix} is treated as 10 (i.e. undefined, 0 or 10). 265 // Check if {radix} is treated as 10 (i.e. undefined, 0 or 10).
274 Label if_radix10(&assembler), if_generic(&assembler, Label::kDeferred); 266 Label if_radix10(this), if_generic(this, Label::kDeferred);
275 assembler.GotoIf(assembler.WordEqual(radix, assembler.UndefinedConstant()), 267 GotoIf(WordEqual(radix, UndefinedConstant()), &if_radix10);
276 &if_radix10); 268 GotoIf(WordEqual(radix, SmiConstant(Smi::FromInt(10))), &if_radix10);
277 assembler.GotoIf( 269 GotoIf(WordEqual(radix, SmiConstant(Smi::FromInt(0))), &if_radix10);
278 assembler.WordEqual(radix, assembler.SmiConstant(Smi::FromInt(10))), 270 Goto(&if_generic);
279 &if_radix10);
280 assembler.GotoIf(
281 assembler.WordEqual(radix, assembler.SmiConstant(Smi::FromInt(0))),
282 &if_radix10);
283 assembler.Goto(&if_generic);
284 271
285 assembler.Bind(&if_radix10); 272 Bind(&if_radix10);
286 { 273 {
287 // Check if we can avoid the ToString conversion on {input}. 274 // Check if we can avoid the ToString conversion on {input}.
288 Label if_inputissmi(&assembler), if_inputisheapnumber(&assembler), 275 Label if_inputissmi(this), if_inputisheapnumber(this),
289 if_inputisstring(&assembler); 276 if_inputisstring(this);
290 assembler.GotoIf(assembler.TaggedIsSmi(input), &if_inputissmi); 277 GotoIf(TaggedIsSmi(input), &if_inputissmi);
291 Node* input_map = assembler.LoadMap(input); 278 Node* input_map = LoadMap(input);
292 assembler.GotoIf( 279 GotoIf(IsHeapNumberMap(input_map), &if_inputisheapnumber);
293 assembler.WordEqual(input_map, assembler.HeapNumberMapConstant()), 280 Node* input_instance_type = LoadMapInstanceType(input_map);
294 &if_inputisheapnumber); 281 Branch(IsStringInstanceType(input_instance_type), &if_inputisstring,
295 Node* input_instance_type = assembler.LoadMapInstanceType(input_map); 282 &if_generic);
296 assembler.Branch(assembler.IsStringInstanceType(input_instance_type),
297 &if_inputisstring, &if_generic);
298 283
299 assembler.Bind(&if_inputissmi); 284 Bind(&if_inputissmi);
300 { 285 {
301 // Just return the {input}. 286 // Just return the {input}.
302 assembler.Return(input); 287 Return(input);
303 } 288 }
304 289
305 assembler.Bind(&if_inputisheapnumber); 290 Bind(&if_inputisheapnumber);
306 { 291 {
307 // Check if the {input} value is in Signed32 range. 292 // Check if the {input} value is in Signed32 range.
308 Label if_inputissigned32(&assembler); 293 Label if_inputissigned32(this);
309 Node* input_value = assembler.LoadHeapNumberValue(input); 294 Node* input_value = LoadHeapNumberValue(input);
310 Node* input_value32 = assembler.TruncateFloat64ToWord32(input_value); 295 Node* input_value32 = TruncateFloat64ToWord32(input_value);
311 assembler.GotoIf( 296 GotoIf(Float64Equal(input_value, ChangeInt32ToFloat64(input_value32)),
312 assembler.Float64Equal(input_value, 297 &if_inputissigned32);
313 assembler.ChangeInt32ToFloat64(input_value32)),
314 &if_inputissigned32);
315 298
316 // Check if the absolute {input} value is in the ]0.01,1e9[ range. 299 // Check if the absolute {input} value is in the ]0.01,1e9[ range.
317 Node* input_value_abs = assembler.Float64Abs(input_value); 300 Node* input_value_abs = Float64Abs(input_value);
318 301
319 assembler.GotoUnless(assembler.Float64LessThan( 302 GotoUnless(Float64LessThan(input_value_abs, Float64Constant(1e9)),
320 input_value_abs, assembler.Float64Constant(1e9)), 303 &if_generic);
321 &if_generic); 304 Branch(Float64LessThan(Float64Constant(0.01), input_value_abs),
322 assembler.Branch(assembler.Float64LessThan( 305 &if_inputissigned32, &if_generic);
323 assembler.Float64Constant(0.01), input_value_abs),
324 &if_inputissigned32, &if_generic);
325 306
326 // Return the truncated int32 value, and return the tagged result. 307 // Return the truncated int32 value, and return the tagged result.
327 assembler.Bind(&if_inputissigned32); 308 Bind(&if_inputissigned32);
328 Node* result = assembler.ChangeInt32ToTagged(input_value32); 309 Node* result = ChangeInt32ToTagged(input_value32);
329 assembler.Return(result); 310 Return(result);
330 } 311 }
331 312
332 assembler.Bind(&if_inputisstring); 313 Bind(&if_inputisstring);
333 { 314 {
334 // Check if the String {input} has a cached array index. 315 // Check if the String {input} has a cached array index.
335 Node* input_hash = assembler.LoadNameHashField(input); 316 Node* input_hash = LoadNameHashField(input);
336 Node* input_bit = assembler.Word32And( 317 Node* input_bit = Word32And(
337 input_hash, 318 input_hash, Int32Constant(String::kContainsCachedArrayIndexMask));
338 assembler.Int32Constant(String::kContainsCachedArrayIndexMask)); 319 GotoIf(Word32NotEqual(input_bit, Int32Constant(0)), &if_generic);
339 assembler.GotoIf(
340 assembler.Word32NotEqual(input_bit, assembler.Int32Constant(0)),
341 &if_generic);
342 320
343 // Return the cached array index as result. 321 // Return the cached array index as result.
344 Node* input_index = 322 Node* input_index =
345 assembler.DecodeWordFromWord32<String::ArrayIndexValueBits>( 323 DecodeWordFromWord32<String::ArrayIndexValueBits>(input_hash);
346 input_hash); 324 Node* result = SmiTag(input_index);
347 Node* result = assembler.SmiTag(input_index); 325 Return(result);
348 assembler.Return(result);
349 } 326 }
350 } 327 }
351 328
352 assembler.Bind(&if_generic); 329 Bind(&if_generic);
353 { 330 {
354 Node* result = 331 Node* result = CallRuntime(Runtime::kStringParseInt, context, input, radix);
355 assembler.CallRuntime(Runtime::kStringParseInt, context, input, radix); 332 Return(result);
356 assembler.Return(result);
357 } 333 }
358 } 334 }
359 335
360 // ES6 section 20.1.3.2 Number.prototype.toExponential ( fractionDigits ) 336 // ES6 section 20.1.3.2 Number.prototype.toExponential ( fractionDigits )
361 BUILTIN(NumberPrototypeToExponential) { 337 BUILTIN(NumberPrototypeToExponential) {
362 HandleScope scope(isolate); 338 HandleScope scope(isolate);
363 Handle<Object> value = args.at<Object>(0); 339 Handle<Object> value = args.at<Object>(0);
364 Handle<Object> fraction_digits = args.atOrUndefined(isolate, 1); 340 Handle<Object> fraction_digits = args.atOrUndefined(isolate, 1);
365 341
366 // Unwrap the receiver {value}. 342 // Unwrap the receiver {value}.
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
559 : isolate->heap()->infinity_string(); 535 : isolate->heap()->infinity_string();
560 } 536 }
561 char* const str = 537 char* const str =
562 DoubleToRadixCString(value_number, static_cast<int>(radix_number)); 538 DoubleToRadixCString(value_number, static_cast<int>(radix_number));
563 Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str); 539 Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
564 DeleteArray(str); 540 DeleteArray(str);
565 return *result; 541 return *result;
566 } 542 }
567 543
568 // ES6 section 20.1.3.7 Number.prototype.valueOf ( ) 544 // ES6 section 20.1.3.7 Number.prototype.valueOf ( )
569 void Builtins::Generate_NumberPrototypeValueOf( 545 TF_BUILTIN(NumberPrototypeValueOf, CodeStubAssembler) {
570 compiler::CodeAssemblerState* state) { 546 Node* receiver = Parameter(0);
571 typedef compiler::Node Node; 547 Node* context = Parameter(3);
572 CodeStubAssembler assembler(state); 548
573 549 Node* result = ToThisValue(context, receiver, PrimitiveType::kNumber,
574 Node* receiver = assembler.Parameter(0); 550 "Number.prototype.valueOf");
575 Node* context = assembler.Parameter(3); 551 Return(result);
576
577 Node* result = assembler.ToThisValue(
578 context, receiver, PrimitiveType::kNumber, "Number.prototype.valueOf");
579 assembler.Return(result);
580 } 552 }
581 553
582 // static 554 TF_BUILTIN(Add, CodeStubAssembler) {
583 void Builtins::Generate_Add(compiler::CodeAssemblerState* state) { 555 Node* left = Parameter(0);
584 typedef CodeStubAssembler::Label Label; 556 Node* right = Parameter(1);
585 typedef compiler::Node Node; 557 Node* context = Parameter(2);
586 typedef CodeStubAssembler::Variable Variable;
587 CodeStubAssembler assembler(state);
588
589 Node* left = assembler.Parameter(0);
590 Node* right = assembler.Parameter(1);
591 Node* context = assembler.Parameter(2);
592 558
593 // Shared entry for floating point addition. 559 // Shared entry for floating point addition.
594 Label do_fadd(&assembler); 560 Label do_fadd(this);
595 Variable var_fadd_lhs(&assembler, MachineRepresentation::kFloat64), 561 Variable var_fadd_lhs(this, MachineRepresentation::kFloat64),
596 var_fadd_rhs(&assembler, MachineRepresentation::kFloat64); 562 var_fadd_rhs(this, MachineRepresentation::kFloat64);
597 563
598 // We might need to loop several times due to ToPrimitive, ToString and/or 564 // We might need to loop several times due to ToPrimitive, ToString and/or
599 // ToNumber conversions. 565 // ToNumber conversions.
600 Variable var_lhs(&assembler, MachineRepresentation::kTagged), 566 Variable var_lhs(this, MachineRepresentation::kTagged),
601 var_rhs(&assembler, MachineRepresentation::kTagged), 567 var_rhs(this, MachineRepresentation::kTagged),
602 var_result(&assembler, MachineRepresentation::kTagged); 568 var_result(this, MachineRepresentation::kTagged);
603 Variable* loop_vars[2] = {&var_lhs, &var_rhs}; 569 Variable* loop_vars[2] = {&var_lhs, &var_rhs};
604 Label loop(&assembler, 2, loop_vars), end(&assembler), 570 Label loop(this, 2, loop_vars), end(this),
605 string_add_convert_left(&assembler, Label::kDeferred), 571 string_add_convert_left(this, Label::kDeferred),
606 string_add_convert_right(&assembler, Label::kDeferred); 572 string_add_convert_right(this, Label::kDeferred);
607 var_lhs.Bind(left); 573 var_lhs.Bind(left);
608 var_rhs.Bind(right); 574 var_rhs.Bind(right);
609 assembler.Goto(&loop); 575 Goto(&loop);
610 assembler.Bind(&loop); 576 Bind(&loop);
611 { 577 {
612 // Load the current {lhs} and {rhs} values. 578 // Load the current {lhs} and {rhs} values.
613 Node* lhs = var_lhs.value(); 579 Node* lhs = var_lhs.value();
614 Node* rhs = var_rhs.value(); 580 Node* rhs = var_rhs.value();
615 581
616 // Check if the {lhs} is a Smi or a HeapObject. 582 // Check if the {lhs} is a Smi or a HeapObject.
617 Label if_lhsissmi(&assembler), if_lhsisnotsmi(&assembler); 583 Label if_lhsissmi(this), if_lhsisnotsmi(this);
618 assembler.Branch(assembler.TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); 584 Branch(TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi);
619 585
620 assembler.Bind(&if_lhsissmi); 586 Bind(&if_lhsissmi);
621 { 587 {
622 // Check if the {rhs} is also a Smi. 588 // Check if the {rhs} is also a Smi.
623 Label if_rhsissmi(&assembler), if_rhsisnotsmi(&assembler); 589 Label if_rhsissmi(this), if_rhsisnotsmi(this);
624 assembler.Branch(assembler.TaggedIsSmi(rhs), &if_rhsissmi, 590 Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
625 &if_rhsisnotsmi); 591
626 592 Bind(&if_rhsissmi);
627 assembler.Bind(&if_rhsissmi);
628 { 593 {
629 // Try fast Smi addition first. 594 // Try fast Smi addition first.
630 Node* pair = 595 Node* pair = IntPtrAddWithOverflow(BitcastTaggedToWord(lhs),
631 assembler.IntPtrAddWithOverflow(assembler.BitcastTaggedToWord(lhs), 596 BitcastTaggedToWord(rhs));
632 assembler.BitcastTaggedToWord(rhs)); 597 Node* overflow = Projection(1, pair);
633 Node* overflow = assembler.Projection(1, pair);
634 598
635 // Check if the Smi additon overflowed. 599 // Check if the Smi additon overflowed.
636 Label if_overflow(&assembler), if_notoverflow(&assembler); 600 Label if_overflow(this), if_notoverflow(this);
637 assembler.Branch(overflow, &if_overflow, &if_notoverflow); 601 Branch(overflow, &if_overflow, &if_notoverflow);
638 602
639 assembler.Bind(&if_overflow); 603 Bind(&if_overflow);
640 { 604 {
641 var_fadd_lhs.Bind(assembler.SmiToFloat64(lhs)); 605 var_fadd_lhs.Bind(SmiToFloat64(lhs));
642 var_fadd_rhs.Bind(assembler.SmiToFloat64(rhs)); 606 var_fadd_rhs.Bind(SmiToFloat64(rhs));
643 assembler.Goto(&do_fadd); 607 Goto(&do_fadd);
644 } 608 }
645 609
646 assembler.Bind(&if_notoverflow); 610 Bind(&if_notoverflow);
647 var_result.Bind( 611 var_result.Bind(BitcastWordToTaggedSigned(Projection(0, pair)));
648 assembler.BitcastWordToTaggedSigned(assembler.Projection(0, pair))); 612 Goto(&end);
649 assembler.Goto(&end);
650 } 613 }
651 614
652 assembler.Bind(&if_rhsisnotsmi); 615 Bind(&if_rhsisnotsmi);
653 { 616 {
654 // Load the map of {rhs}. 617 // Load the map of {rhs}.
655 Node* rhs_map = assembler.LoadMap(rhs); 618 Node* rhs_map = LoadMap(rhs);
656 619
657 // Check if the {rhs} is a HeapNumber. 620 // Check if the {rhs} is a HeapNumber.
658 Label if_rhsisnumber(&assembler), 621 Label if_rhsisnumber(this), if_rhsisnotnumber(this, Label::kDeferred);
659 if_rhsisnotnumber(&assembler, Label::kDeferred); 622 Branch(IsHeapNumberMap(rhs_map), &if_rhsisnumber, &if_rhsisnotnumber);
660 assembler.Branch(assembler.IsHeapNumberMap(rhs_map), &if_rhsisnumber, 623
661 &if_rhsisnotnumber); 624 Bind(&if_rhsisnumber);
662 625 {
663 assembler.Bind(&if_rhsisnumber); 626 var_fadd_lhs.Bind(SmiToFloat64(lhs));
664 { 627 var_fadd_rhs.Bind(LoadHeapNumberValue(rhs));
665 var_fadd_lhs.Bind(assembler.SmiToFloat64(lhs)); 628 Goto(&do_fadd);
666 var_fadd_rhs.Bind(assembler.LoadHeapNumberValue(rhs));
667 assembler.Goto(&do_fadd);
668 } 629 }
669 630
670 assembler.Bind(&if_rhsisnotnumber); 631 Bind(&if_rhsisnotnumber);
671 { 632 {
672 // Load the instance type of {rhs}. 633 // Load the instance type of {rhs}.
673 Node* rhs_instance_type = assembler.LoadMapInstanceType(rhs_map); 634 Node* rhs_instance_type = LoadMapInstanceType(rhs_map);
674 635
675 // Check if the {rhs} is a String. 636 // Check if the {rhs} is a String.
676 Label if_rhsisstring(&assembler, Label::kDeferred), 637 Label if_rhsisstring(this, Label::kDeferred),
677 if_rhsisnotstring(&assembler, Label::kDeferred); 638 if_rhsisnotstring(this, Label::kDeferred);
678 assembler.Branch(assembler.IsStringInstanceType(rhs_instance_type), 639 Branch(IsStringInstanceType(rhs_instance_type), &if_rhsisstring,
679 &if_rhsisstring, &if_rhsisnotstring); 640 &if_rhsisnotstring);
680 641
681 assembler.Bind(&if_rhsisstring); 642 Bind(&if_rhsisstring);
682 { 643 {
683 var_lhs.Bind(lhs); 644 var_lhs.Bind(lhs);
684 var_rhs.Bind(rhs); 645 var_rhs.Bind(rhs);
685 assembler.Goto(&string_add_convert_left); 646 Goto(&string_add_convert_left);
686 } 647 }
687 648
688 assembler.Bind(&if_rhsisnotstring); 649 Bind(&if_rhsisnotstring);
689 { 650 {
690 // Check if {rhs} is a JSReceiver. 651 // Check if {rhs} is a JSReceiver.
691 Label if_rhsisreceiver(&assembler, Label::kDeferred), 652 Label if_rhsisreceiver(this, Label::kDeferred),
692 if_rhsisnotreceiver(&assembler, Label::kDeferred); 653 if_rhsisnotreceiver(this, Label::kDeferred);
693 assembler.Branch( 654 Branch(IsJSReceiverInstanceType(rhs_instance_type),
694 assembler.IsJSReceiverInstanceType(rhs_instance_type), 655 &if_rhsisreceiver, &if_rhsisnotreceiver);
695 &if_rhsisreceiver, &if_rhsisnotreceiver); 656
696 657 Bind(&if_rhsisreceiver);
697 assembler.Bind(&if_rhsisreceiver);
698 { 658 {
699 // Convert {rhs} to a primitive first passing no hint. 659 // Convert {rhs} to a primitive first passing no hint.
700 Callable callable = 660 Callable callable =
701 CodeFactory::NonPrimitiveToPrimitive(assembler.isolate()); 661 CodeFactory::NonPrimitiveToPrimitive(isolate());
702 var_rhs.Bind(assembler.CallStub(callable, context, rhs)); 662 var_rhs.Bind(CallStub(callable, context, rhs));
703 assembler.Goto(&loop); 663 Goto(&loop);
704 } 664 }
705 665
706 assembler.Bind(&if_rhsisnotreceiver); 666 Bind(&if_rhsisnotreceiver);
707 { 667 {
708 // Convert {rhs} to a Number first. 668 // Convert {rhs} to a Number first.
709 Callable callable = 669 Callable callable = CodeFactory::NonNumberToNumber(isolate());
710 CodeFactory::NonNumberToNumber(assembler.isolate()); 670 var_rhs.Bind(CallStub(callable, context, rhs));
711 var_rhs.Bind(assembler.CallStub(callable, context, rhs)); 671 Goto(&loop);
712 assembler.Goto(&loop);
713 } 672 }
714 } 673 }
715 } 674 }
716 } 675 }
717 } 676 }
718 677
719 assembler.Bind(&if_lhsisnotsmi); 678 Bind(&if_lhsisnotsmi);
720 { 679 {
721 // Load the map and instance type of {lhs}. 680 // Load the map and instance type of {lhs}.
722 Node* lhs_instance_type = assembler.LoadInstanceType(lhs); 681 Node* lhs_instance_type = LoadInstanceType(lhs);
723 682
724 // Check if {lhs} is a String. 683 // Check if {lhs} is a String.
725 Label if_lhsisstring(&assembler), if_lhsisnotstring(&assembler); 684 Label if_lhsisstring(this), if_lhsisnotstring(this);
726 assembler.Branch(assembler.IsStringInstanceType(lhs_instance_type), 685 Branch(IsStringInstanceType(lhs_instance_type), &if_lhsisstring,
727 &if_lhsisstring, &if_lhsisnotstring); 686 &if_lhsisnotstring);
728 687
729 assembler.Bind(&if_lhsisstring); 688 Bind(&if_lhsisstring);
730 { 689 {
731 var_lhs.Bind(lhs); 690 var_lhs.Bind(lhs);
732 var_rhs.Bind(rhs); 691 var_rhs.Bind(rhs);
733 assembler.Goto(&string_add_convert_right); 692 Goto(&string_add_convert_right);
734 } 693 }
735 694
736 assembler.Bind(&if_lhsisnotstring); 695 Bind(&if_lhsisnotstring);
737 { 696 {
738 // Check if {rhs} is a Smi. 697 // Check if {rhs} is a Smi.
739 Label if_rhsissmi(&assembler), if_rhsisnotsmi(&assembler); 698 Label if_rhsissmi(this), if_rhsisnotsmi(this);
740 assembler.Branch(assembler.TaggedIsSmi(rhs), &if_rhsissmi, 699 Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
741 &if_rhsisnotsmi); 700
742 701 Bind(&if_rhsissmi);
743 assembler.Bind(&if_rhsissmi);
744 { 702 {
745 // Check if {lhs} is a Number. 703 // Check if {lhs} is a Number.
746 Label if_lhsisnumber(&assembler), 704 Label if_lhsisnumber(this), if_lhsisnotnumber(this, Label::kDeferred);
747 if_lhsisnotnumber(&assembler, Label::kDeferred); 705 Branch(
748 assembler.Branch( 706 Word32Equal(lhs_instance_type, Int32Constant(HEAP_NUMBER_TYPE)),
749 assembler.Word32Equal(lhs_instance_type,
750 assembler.Int32Constant(HEAP_NUMBER_TYPE)),
751 &if_lhsisnumber, &if_lhsisnotnumber); 707 &if_lhsisnumber, &if_lhsisnotnumber);
752 708
753 assembler.Bind(&if_lhsisnumber); 709 Bind(&if_lhsisnumber);
754 { 710 {
755 // The {lhs} is a HeapNumber, the {rhs} is a Smi, just add them. 711 // The {lhs} is a HeapNumber, the {rhs} is a Smi, just add them.
756 var_fadd_lhs.Bind(assembler.LoadHeapNumberValue(lhs)); 712 var_fadd_lhs.Bind(LoadHeapNumberValue(lhs));
757 var_fadd_rhs.Bind(assembler.SmiToFloat64(rhs)); 713 var_fadd_rhs.Bind(SmiToFloat64(rhs));
758 assembler.Goto(&do_fadd); 714 Goto(&do_fadd);
759 } 715 }
760 716
761 assembler.Bind(&if_lhsisnotnumber); 717 Bind(&if_lhsisnotnumber);
762 { 718 {
763 // The {lhs} is neither a Number nor a String, and the {rhs} is a 719 // The {lhs} is neither a Number nor a String, and the {rhs} is a
764 // Smi. 720 // Smi.
765 Label if_lhsisreceiver(&assembler, Label::kDeferred), 721 Label if_lhsisreceiver(this, Label::kDeferred),
766 if_lhsisnotreceiver(&assembler, Label::kDeferred); 722 if_lhsisnotreceiver(this, Label::kDeferred);
767 assembler.Branch( 723 Branch(IsJSReceiverInstanceType(lhs_instance_type),
768 assembler.IsJSReceiverInstanceType(lhs_instance_type), 724 &if_lhsisreceiver, &if_lhsisnotreceiver);
769 &if_lhsisreceiver, &if_lhsisnotreceiver); 725
770 726 Bind(&if_lhsisreceiver);
771 assembler.Bind(&if_lhsisreceiver);
772 { 727 {
773 // Convert {lhs} to a primitive first passing no hint. 728 // Convert {lhs} to a primitive first passing no hint.
774 Callable callable = 729 Callable callable =
775 CodeFactory::NonPrimitiveToPrimitive(assembler.isolate()); 730 CodeFactory::NonPrimitiveToPrimitive(isolate());
776 var_lhs.Bind(assembler.CallStub(callable, context, lhs)); 731 var_lhs.Bind(CallStub(callable, context, lhs));
777 assembler.Goto(&loop); 732 Goto(&loop);
778 } 733 }
779 734
780 assembler.Bind(&if_lhsisnotreceiver); 735 Bind(&if_lhsisnotreceiver);
781 { 736 {
782 // Convert {lhs} to a Number first. 737 // Convert {lhs} to a Number first.
783 Callable callable = 738 Callable callable = CodeFactory::NonNumberToNumber(isolate());
784 CodeFactory::NonNumberToNumber(assembler.isolate()); 739 var_lhs.Bind(CallStub(callable, context, lhs));
785 var_lhs.Bind(assembler.CallStub(callable, context, lhs)); 740 Goto(&loop);
786 assembler.Goto(&loop);
787 } 741 }
788 } 742 }
789 } 743 }
790 744
791 assembler.Bind(&if_rhsisnotsmi); 745 Bind(&if_rhsisnotsmi);
792 { 746 {
793 // Load the instance type of {rhs}. 747 // Load the instance type of {rhs}.
794 Node* rhs_instance_type = assembler.LoadInstanceType(rhs); 748 Node* rhs_instance_type = LoadInstanceType(rhs);
795 749
796 // Check if {rhs} is a String. 750 // Check if {rhs} is a String.
797 Label if_rhsisstring(&assembler), if_rhsisnotstring(&assembler); 751 Label if_rhsisstring(this), if_rhsisnotstring(this);
798 assembler.Branch(assembler.IsStringInstanceType(rhs_instance_type), 752 Branch(IsStringInstanceType(rhs_instance_type), &if_rhsisstring,
799 &if_rhsisstring, &if_rhsisnotstring); 753 &if_rhsisnotstring);
800 754
801 assembler.Bind(&if_rhsisstring); 755 Bind(&if_rhsisstring);
802 { 756 {
803 var_lhs.Bind(lhs); 757 var_lhs.Bind(lhs);
804 var_rhs.Bind(rhs); 758 var_rhs.Bind(rhs);
805 assembler.Goto(&string_add_convert_left); 759 Goto(&string_add_convert_left);
806 } 760 }
807 761
808 assembler.Bind(&if_rhsisnotstring); 762 Bind(&if_rhsisnotstring);
809 { 763 {
810 // Check if {lhs} is a HeapNumber. 764 // Check if {lhs} is a HeapNumber.
811 Label if_lhsisnumber(&assembler), if_lhsisnotnumber(&assembler); 765 Label if_lhsisnumber(this), if_lhsisnotnumber(this);
812 assembler.Branch(assembler.Word32Equal( 766 Branch(
813 lhs_instance_type, 767 Word32Equal(lhs_instance_type, Int32Constant(HEAP_NUMBER_TYPE)),
814 assembler.Int32Constant(HEAP_NUMBER_TYPE)), 768 &if_lhsisnumber, &if_lhsisnotnumber);
815 &if_lhsisnumber, &if_lhsisnotnumber); 769
816 770 Bind(&if_lhsisnumber);
817 assembler.Bind(&if_lhsisnumber);
818 { 771 {
819 // Check if {rhs} is also a HeapNumber. 772 // Check if {rhs} is also a HeapNumber.
820 Label if_rhsisnumber(&assembler), 773 Label if_rhsisnumber(this),
821 if_rhsisnotnumber(&assembler, Label::kDeferred); 774 if_rhsisnotnumber(this, Label::kDeferred);
822 assembler.Branch(assembler.Word32Equal( 775 Branch(Word32Equal(rhs_instance_type,
823 rhs_instance_type, 776 Int32Constant(HEAP_NUMBER_TYPE)),
824 assembler.Int32Constant(HEAP_NUMBER_TYPE)), 777 &if_rhsisnumber, &if_rhsisnotnumber);
825 &if_rhsisnumber, &if_rhsisnotnumber); 778
826 779 Bind(&if_rhsisnumber);
827 assembler.Bind(&if_rhsisnumber);
828 { 780 {
829 // Perform a floating point addition. 781 // Perform a floating point addition.
830 var_fadd_lhs.Bind(assembler.LoadHeapNumberValue(lhs)); 782 var_fadd_lhs.Bind(LoadHeapNumberValue(lhs));
831 var_fadd_rhs.Bind(assembler.LoadHeapNumberValue(rhs)); 783 var_fadd_rhs.Bind(LoadHeapNumberValue(rhs));
832 assembler.Goto(&do_fadd); 784 Goto(&do_fadd);
833 } 785 }
834 786
835 assembler.Bind(&if_rhsisnotnumber); 787 Bind(&if_rhsisnotnumber);
836 { 788 {
837 // Check if {rhs} is a JSReceiver. 789 // Check if {rhs} is a JSReceiver.
838 Label if_rhsisreceiver(&assembler, Label::kDeferred), 790 Label if_rhsisreceiver(this, Label::kDeferred),
839 if_rhsisnotreceiver(&assembler, Label::kDeferred); 791 if_rhsisnotreceiver(this, Label::kDeferred);
840 assembler.Branch( 792 Branch(IsJSReceiverInstanceType(rhs_instance_type),
841 assembler.IsJSReceiverInstanceType(rhs_instance_type), 793 &if_rhsisreceiver, &if_rhsisnotreceiver);
842 &if_rhsisreceiver, &if_rhsisnotreceiver); 794
843 795 Bind(&if_rhsisreceiver);
844 assembler.Bind(&if_rhsisreceiver);
845 { 796 {
846 // Convert {rhs} to a primitive first passing no hint. 797 // Convert {rhs} to a primitive first passing no hint.
847 Callable callable = 798 Callable callable =
848 CodeFactory::NonPrimitiveToPrimitive(assembler.isolate()); 799 CodeFactory::NonPrimitiveToPrimitive(isolate());
849 var_rhs.Bind(assembler.CallStub(callable, context, rhs)); 800 var_rhs.Bind(CallStub(callable, context, rhs));
850 assembler.Goto(&loop); 801 Goto(&loop);
851 } 802 }
852 803
853 assembler.Bind(&if_rhsisnotreceiver); 804 Bind(&if_rhsisnotreceiver);
854 { 805 {
855 // Convert {rhs} to a Number first. 806 // Convert {rhs} to a Number first.
856 Callable callable = 807 Callable callable = CodeFactory::NonNumberToNumber(isolate());
857 CodeFactory::NonNumberToNumber(assembler.isolate()); 808 var_rhs.Bind(CallStub(callable, context, rhs));
858 var_rhs.Bind(assembler.CallStub(callable, context, rhs)); 809 Goto(&loop);
859 assembler.Goto(&loop);
860 } 810 }
861 } 811 }
862 } 812 }
863 813
864 assembler.Bind(&if_lhsisnotnumber); 814 Bind(&if_lhsisnotnumber);
865 { 815 {
866 // Check if {lhs} is a JSReceiver. 816 // Check if {lhs} is a JSReceiver.
867 Label if_lhsisreceiver(&assembler, Label::kDeferred), 817 Label if_lhsisreceiver(this, Label::kDeferred),
868 if_lhsisnotreceiver(&assembler); 818 if_lhsisnotreceiver(this);
869 assembler.Branch( 819 Branch(IsJSReceiverInstanceType(lhs_instance_type),
870 assembler.IsJSReceiverInstanceType(lhs_instance_type), 820 &if_lhsisreceiver, &if_lhsisnotreceiver);
871 &if_lhsisreceiver, &if_lhsisnotreceiver); 821
872 822 Bind(&if_lhsisreceiver);
873 assembler.Bind(&if_lhsisreceiver);
874 { 823 {
875 // Convert {lhs} to a primitive first passing no hint. 824 // Convert {lhs} to a primitive first passing no hint.
876 Callable callable = 825 Callable callable =
877 CodeFactory::NonPrimitiveToPrimitive(assembler.isolate()); 826 CodeFactory::NonPrimitiveToPrimitive(isolate());
878 var_lhs.Bind(assembler.CallStub(callable, context, lhs)); 827 var_lhs.Bind(CallStub(callable, context, lhs));
879 assembler.Goto(&loop); 828 Goto(&loop);
880 } 829 }
881 830
882 assembler.Bind(&if_lhsisnotreceiver); 831 Bind(&if_lhsisnotreceiver);
883 { 832 {
884 // Check if {rhs} is a JSReceiver. 833 // Check if {rhs} is a JSReceiver.
885 Label if_rhsisreceiver(&assembler, Label::kDeferred), 834 Label if_rhsisreceiver(this, Label::kDeferred),
886 if_rhsisnotreceiver(&assembler, Label::kDeferred); 835 if_rhsisnotreceiver(this, Label::kDeferred);
887 assembler.Branch( 836 Branch(IsJSReceiverInstanceType(rhs_instance_type),
888 assembler.IsJSReceiverInstanceType(rhs_instance_type), 837 &if_rhsisreceiver, &if_rhsisnotreceiver);
889 &if_rhsisreceiver, &if_rhsisnotreceiver); 838
890 839 Bind(&if_rhsisreceiver);
891 assembler.Bind(&if_rhsisreceiver);
892 { 840 {
893 // Convert {rhs} to a primitive first passing no hint. 841 // Convert {rhs} to a primitive first passing no hint.
894 Callable callable = 842 Callable callable =
895 CodeFactory::NonPrimitiveToPrimitive(assembler.isolate()); 843 CodeFactory::NonPrimitiveToPrimitive(isolate());
896 var_rhs.Bind(assembler.CallStub(callable, context, rhs)); 844 var_rhs.Bind(CallStub(callable, context, rhs));
897 assembler.Goto(&loop); 845 Goto(&loop);
898 } 846 }
899 847
900 assembler.Bind(&if_rhsisnotreceiver); 848 Bind(&if_rhsisnotreceiver);
901 { 849 {
902 // Convert {lhs} to a Number first. 850 // Convert {lhs} to a Number first.
903 Callable callable = 851 Callable callable = CodeFactory::NonNumberToNumber(isolate());
904 CodeFactory::NonNumberToNumber(assembler.isolate()); 852 var_lhs.Bind(CallStub(callable, context, lhs));
905 var_lhs.Bind(assembler.CallStub(callable, context, lhs)); 853 Goto(&loop);
906 assembler.Goto(&loop);
907 } 854 }
908 } 855 }
909 } 856 }
910 } 857 }
911 } 858 }
912 } 859 }
913 } 860 }
914 } 861 }
915 assembler.Bind(&string_add_convert_left); 862 Bind(&string_add_convert_left);
863 {
864 // Convert {lhs}, which is a Smi, to a String and concatenate the
865 // resulting string with the String {rhs}.
866 Callable callable =
867 CodeFactory::StringAdd(isolate(), STRING_ADD_CONVERT_LEFT, NOT_TENURED);
868 var_result.Bind(
869 CallStub(callable, context, var_lhs.value(), var_rhs.value()));
870 Goto(&end);
871 }
872
873 Bind(&string_add_convert_right);
916 { 874 {
917 // Convert {lhs}, which is a Smi, to a String and concatenate the 875 // Convert {lhs}, which is a Smi, to a String and concatenate the
918 // resulting string with the String {rhs}. 876 // resulting string with the String {rhs}.
919 Callable callable = CodeFactory::StringAdd( 877 Callable callable = CodeFactory::StringAdd(
920 assembler.isolate(), STRING_ADD_CONVERT_LEFT, NOT_TENURED); 878 isolate(), STRING_ADD_CONVERT_RIGHT, NOT_TENURED);
921 var_result.Bind(assembler.CallStub(callable, context, var_lhs.value(), 879 var_result.Bind(
922 var_rhs.value())); 880 CallStub(callable, context, var_lhs.value(), var_rhs.value()));
923 assembler.Goto(&end); 881 Goto(&end);
924 } 882 }
925 883
926 assembler.Bind(&string_add_convert_right); 884 Bind(&do_fadd);
927 {
928 // Convert {lhs}, which is a Smi, to a String and concatenate the
929 // resulting string with the String {rhs}.
930 Callable callable = CodeFactory::StringAdd(
931 assembler.isolate(), STRING_ADD_CONVERT_RIGHT, NOT_TENURED);
932 var_result.Bind(assembler.CallStub(callable, context, var_lhs.value(),
933 var_rhs.value()));
934 assembler.Goto(&end);
935 }
936
937 assembler.Bind(&do_fadd);
938 { 885 {
939 Node* lhs_value = var_fadd_lhs.value(); 886 Node* lhs_value = var_fadd_lhs.value();
940 Node* rhs_value = var_fadd_rhs.value(); 887 Node* rhs_value = var_fadd_rhs.value();
941 Node* value = assembler.Float64Add(lhs_value, rhs_value); 888 Node* value = Float64Add(lhs_value, rhs_value);
942 Node* result = assembler.AllocateHeapNumberWithValue(value); 889 Node* result = AllocateHeapNumberWithValue(value);
943 var_result.Bind(result); 890 var_result.Bind(result);
944 assembler.Goto(&end); 891 Goto(&end);
945 } 892 }
946 assembler.Bind(&end); 893 Bind(&end);
947 assembler.Return(var_result.value()); 894 Return(var_result.value());
948 } 895 }
949 896
950 void Builtins::Generate_Subtract(compiler::CodeAssemblerState* state) { 897 TF_BUILTIN(Subtract, CodeStubAssembler) {
951 typedef CodeStubAssembler::Label Label; 898 Node* left = Parameter(0);
952 typedef compiler::Node Node; 899 Node* right = Parameter(1);
953 typedef CodeStubAssembler::Variable Variable; 900 Node* context = Parameter(2);
954 CodeStubAssembler assembler(state);
955
956 Node* left = assembler.Parameter(0);
957 Node* right = assembler.Parameter(1);
958 Node* context = assembler.Parameter(2);
959 901
960 // Shared entry for floating point subtraction. 902 // Shared entry for floating point subtraction.
961 Label do_fsub(&assembler), end(&assembler); 903 Label do_fsub(this), end(this);
962 Variable var_fsub_lhs(&assembler, MachineRepresentation::kFloat64), 904 Variable var_fsub_lhs(this, MachineRepresentation::kFloat64),
963 var_fsub_rhs(&assembler, MachineRepresentation::kFloat64); 905 var_fsub_rhs(this, MachineRepresentation::kFloat64);
964 906
965 // We might need to loop several times due to ToPrimitive and/or ToNumber 907 // We might need to loop several times due to ToPrimitive and/or ToNumber
966 // conversions. 908 // conversions.
967 Variable var_lhs(&assembler, MachineRepresentation::kTagged), 909 Variable var_lhs(this, MachineRepresentation::kTagged),
968 var_rhs(&assembler, MachineRepresentation::kTagged), 910 var_rhs(this, MachineRepresentation::kTagged),
969 var_result(&assembler, MachineRepresentation::kTagged); 911 var_result(this, MachineRepresentation::kTagged);
970 Variable* loop_vars[2] = {&var_lhs, &var_rhs}; 912 Variable* loop_vars[2] = {&var_lhs, &var_rhs};
971 Label loop(&assembler, 2, loop_vars); 913 Label loop(this, 2, loop_vars);
972 var_lhs.Bind(left); 914 var_lhs.Bind(left);
973 var_rhs.Bind(right); 915 var_rhs.Bind(right);
974 assembler.Goto(&loop); 916 Goto(&loop);
975 assembler.Bind(&loop); 917 Bind(&loop);
976 { 918 {
977 // Load the current {lhs} and {rhs} values. 919 // Load the current {lhs} and {rhs} values.
978 Node* lhs = var_lhs.value(); 920 Node* lhs = var_lhs.value();
979 Node* rhs = var_rhs.value(); 921 Node* rhs = var_rhs.value();
980 922
981 // Check if the {lhs} is a Smi or a HeapObject. 923 // Check if the {lhs} is a Smi or a HeapObject.
982 Label if_lhsissmi(&assembler), if_lhsisnotsmi(&assembler); 924 Label if_lhsissmi(this), if_lhsisnotsmi(this);
983 assembler.Branch(assembler.TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); 925 Branch(TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi);
984 926
985 assembler.Bind(&if_lhsissmi); 927 Bind(&if_lhsissmi);
986 { 928 {
987 // Check if the {rhs} is also a Smi. 929 // Check if the {rhs} is also a Smi.
988 Label if_rhsissmi(&assembler), if_rhsisnotsmi(&assembler); 930 Label if_rhsissmi(this), if_rhsisnotsmi(this);
989 assembler.Branch(assembler.TaggedIsSmi(rhs), &if_rhsissmi, 931 Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
990 &if_rhsisnotsmi); 932
991 933 Bind(&if_rhsissmi);
992 assembler.Bind(&if_rhsissmi);
993 { 934 {
994 // Try a fast Smi subtraction first. 935 // Try a fast Smi subtraction first.
995 Node* pair = 936 Node* pair = IntPtrSubWithOverflow(BitcastTaggedToWord(lhs),
996 assembler.IntPtrSubWithOverflow(assembler.BitcastTaggedToWord(lhs), 937 BitcastTaggedToWord(rhs));
997 assembler.BitcastTaggedToWord(rhs)); 938 Node* overflow = Projection(1, pair);
998 Node* overflow = assembler.Projection(1, pair);
999 939
1000 // Check if the Smi subtraction overflowed. 940 // Check if the Smi subtraction overflowed.
1001 Label if_overflow(&assembler), if_notoverflow(&assembler); 941 Label if_overflow(this), if_notoverflow(this);
1002 assembler.Branch(overflow, &if_overflow, &if_notoverflow); 942 Branch(overflow, &if_overflow, &if_notoverflow);
1003 943
1004 assembler.Bind(&if_overflow); 944 Bind(&if_overflow);
1005 { 945 {
1006 // The result doesn't fit into Smi range. 946 // The result doesn't fit into Smi range.
1007 var_fsub_lhs.Bind(assembler.SmiToFloat64(lhs)); 947 var_fsub_lhs.Bind(SmiToFloat64(lhs));
1008 var_fsub_rhs.Bind(assembler.SmiToFloat64(rhs)); 948 var_fsub_rhs.Bind(SmiToFloat64(rhs));
1009 assembler.Goto(&do_fsub); 949 Goto(&do_fsub);
1010 } 950 }
1011 951
1012 assembler.Bind(&if_notoverflow); 952 Bind(&if_notoverflow);
1013 var_result.Bind( 953 var_result.Bind(BitcastWordToTaggedSigned(Projection(0, pair)));
1014 assembler.BitcastWordToTaggedSigned(assembler.Projection(0, pair))); 954 Goto(&end);
1015 assembler.Goto(&end); 955 }
1016 } 956
1017 957 Bind(&if_rhsisnotsmi);
1018 assembler.Bind(&if_rhsisnotsmi);
1019 { 958 {
1020 // Load the map of the {rhs}. 959 // Load the map of the {rhs}.
1021 Node* rhs_map = assembler.LoadMap(rhs); 960 Node* rhs_map = LoadMap(rhs);
1022 961
1023 // Check if {rhs} is a HeapNumber. 962 // Check if {rhs} is a HeapNumber.
1024 Label if_rhsisnumber(&assembler), 963 Label if_rhsisnumber(this), if_rhsisnotnumber(this, Label::kDeferred);
1025 if_rhsisnotnumber(&assembler, Label::kDeferred); 964 Branch(IsHeapNumberMap(rhs_map), &if_rhsisnumber, &if_rhsisnotnumber);
1026 assembler.Branch(assembler.IsHeapNumberMap(rhs_map), &if_rhsisnumber, 965
1027 &if_rhsisnotnumber); 966 Bind(&if_rhsisnumber);
1028
1029 assembler.Bind(&if_rhsisnumber);
1030 { 967 {
1031 // Perform a floating point subtraction. 968 // Perform a floating point subtraction.
1032 var_fsub_lhs.Bind(assembler.SmiToFloat64(lhs)); 969 var_fsub_lhs.Bind(SmiToFloat64(lhs));
1033 var_fsub_rhs.Bind(assembler.LoadHeapNumberValue(rhs)); 970 var_fsub_rhs.Bind(LoadHeapNumberValue(rhs));
1034 assembler.Goto(&do_fsub); 971 Goto(&do_fsub);
1035 } 972 }
1036 973
1037 assembler.Bind(&if_rhsisnotnumber); 974 Bind(&if_rhsisnotnumber);
1038 { 975 {
1039 // Convert the {rhs} to a Number first. 976 // Convert the {rhs} to a Number first.
1040 Callable callable = 977 Callable callable = CodeFactory::NonNumberToNumber(isolate());
1041 CodeFactory::NonNumberToNumber(assembler.isolate()); 978 var_rhs.Bind(CallStub(callable, context, rhs));
1042 var_rhs.Bind(assembler.CallStub(callable, context, rhs)); 979 Goto(&loop);
1043 assembler.Goto(&loop); 980 }
1044 } 981 }
1045 } 982 }
1046 } 983
1047 984 Bind(&if_lhsisnotsmi);
1048 assembler.Bind(&if_lhsisnotsmi);
1049 { 985 {
1050 // Load the map of the {lhs}. 986 // Load the map of the {lhs}.
1051 Node* lhs_map = assembler.LoadMap(lhs); 987 Node* lhs_map = LoadMap(lhs);
1052 988
1053 // Check if the {lhs} is a HeapNumber. 989 // Check if the {lhs} is a HeapNumber.
1054 Label if_lhsisnumber(&assembler), 990 Label if_lhsisnumber(this), if_lhsisnotnumber(this, Label::kDeferred);
1055 if_lhsisnotnumber(&assembler, Label::kDeferred); 991 Node* number_map = HeapNumberMapConstant();
1056 Node* number_map = assembler.HeapNumberMapConstant(); 992 Branch(WordEqual(lhs_map, number_map), &if_lhsisnumber,
1057 assembler.Branch(assembler.WordEqual(lhs_map, number_map), 993 &if_lhsisnotnumber);
1058 &if_lhsisnumber, &if_lhsisnotnumber); 994
1059 995 Bind(&if_lhsisnumber);
1060 assembler.Bind(&if_lhsisnumber);
1061 { 996 {
1062 // Check if the {rhs} is a Smi. 997 // Check if the {rhs} is a Smi.
1063 Label if_rhsissmi(&assembler), if_rhsisnotsmi(&assembler); 998 Label if_rhsissmi(this), if_rhsisnotsmi(this);
1064 assembler.Branch(assembler.TaggedIsSmi(rhs), &if_rhsissmi, 999 Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
1065 &if_rhsisnotsmi); 1000
1066 1001 Bind(&if_rhsissmi);
1067 assembler.Bind(&if_rhsissmi);
1068 { 1002 {
1069 // Perform a floating point subtraction. 1003 // Perform a floating point subtraction.
1070 var_fsub_lhs.Bind(assembler.LoadHeapNumberValue(lhs)); 1004 var_fsub_lhs.Bind(LoadHeapNumberValue(lhs));
1071 var_fsub_rhs.Bind(assembler.SmiToFloat64(rhs)); 1005 var_fsub_rhs.Bind(SmiToFloat64(rhs));
1072 assembler.Goto(&do_fsub); 1006 Goto(&do_fsub);
1073 } 1007 }
1074 1008
1075 assembler.Bind(&if_rhsisnotsmi); 1009 Bind(&if_rhsisnotsmi);
1076 { 1010 {
1077 // Load the map of the {rhs}. 1011 // Load the map of the {rhs}.
1078 Node* rhs_map = assembler.LoadMap(rhs); 1012 Node* rhs_map = LoadMap(rhs);
1079 1013
1080 // Check if the {rhs} is a HeapNumber. 1014 // Check if the {rhs} is a HeapNumber.
1081 Label if_rhsisnumber(&assembler), 1015 Label if_rhsisnumber(this), if_rhsisnotnumber(this, Label::kDeferred);
1082 if_rhsisnotnumber(&assembler, Label::kDeferred); 1016 Branch(WordEqual(rhs_map, number_map), &if_rhsisnumber,
1083 assembler.Branch(assembler.WordEqual(rhs_map, number_map), 1017 &if_rhsisnotnumber);
1084 &if_rhsisnumber, &if_rhsisnotnumber); 1018
1085 1019 Bind(&if_rhsisnumber);
1086 assembler.Bind(&if_rhsisnumber);
1087 { 1020 {
1088 // Perform a floating point subtraction. 1021 // Perform a floating point subtraction.
1089 var_fsub_lhs.Bind(assembler.LoadHeapNumberValue(lhs)); 1022 var_fsub_lhs.Bind(LoadHeapNumberValue(lhs));
1090 var_fsub_rhs.Bind(assembler.LoadHeapNumberValue(rhs)); 1023 var_fsub_rhs.Bind(LoadHeapNumberValue(rhs));
1091 assembler.Goto(&do_fsub); 1024 Goto(&do_fsub);
1092 } 1025 }
1093 1026
1094 assembler.Bind(&if_rhsisnotnumber); 1027 Bind(&if_rhsisnotnumber);
1095 { 1028 {
1096 // Convert the {rhs} to a Number first. 1029 // Convert the {rhs} to a Number first.
1097 Callable callable = 1030 Callable callable = CodeFactory::NonNumberToNumber(isolate());
1098 CodeFactory::NonNumberToNumber(assembler.isolate()); 1031 var_rhs.Bind(CallStub(callable, context, rhs));
1099 var_rhs.Bind(assembler.CallStub(callable, context, rhs)); 1032 Goto(&loop);
1100 assembler.Goto(&loop);
1101 } 1033 }
1102 } 1034 }
1103 } 1035 }
1104 1036
1105 assembler.Bind(&if_lhsisnotnumber); 1037 Bind(&if_lhsisnotnumber);
1106 { 1038 {
1107 // Convert the {lhs} to a Number first. 1039 // Convert the {lhs} to a Number first.
1108 Callable callable = CodeFactory::NonNumberToNumber(assembler.isolate()); 1040 Callable callable = CodeFactory::NonNumberToNumber(isolate());
1109 var_lhs.Bind(assembler.CallStub(callable, context, lhs)); 1041 var_lhs.Bind(CallStub(callable, context, lhs));
1110 assembler.Goto(&loop); 1042 Goto(&loop);
1111 } 1043 }
1112 } 1044 }
1113 } 1045 }
1114 1046
1115 assembler.Bind(&do_fsub); 1047 Bind(&do_fsub);
1116 { 1048 {
1117 Node* lhs_value = var_fsub_lhs.value(); 1049 Node* lhs_value = var_fsub_lhs.value();
1118 Node* rhs_value = var_fsub_rhs.value(); 1050 Node* rhs_value = var_fsub_rhs.value();
1119 Node* value = assembler.Float64Sub(lhs_value, rhs_value); 1051 Node* value = Float64Sub(lhs_value, rhs_value);
1120 var_result.Bind(assembler.AllocateHeapNumberWithValue(value)); 1052 var_result.Bind(AllocateHeapNumberWithValue(value));
1121 assembler.Goto(&end); 1053 Goto(&end);
1122 } 1054 }
1123 assembler.Bind(&end); 1055 Bind(&end);
1124 assembler.Return(var_result.value()); 1056 Return(var_result.value());
1125 } 1057 }
1126 1058
1127 void Builtins::Generate_Multiply(compiler::CodeAssemblerState* state) { 1059 TF_BUILTIN(Multiply, CodeStubAssembler) {
1128 typedef CodeStubAssembler::Label Label; 1060 Node* left = Parameter(0);
1129 typedef compiler::Node Node; 1061 Node* right = Parameter(1);
1130 typedef CodeStubAssembler::Variable Variable; 1062 Node* context = Parameter(2);
1131 CodeStubAssembler assembler(state);
1132
1133 Node* left = assembler.Parameter(0);
1134 Node* right = assembler.Parameter(1);
1135 Node* context = assembler.Parameter(2);
1136 1063
1137 // Shared entry point for floating point multiplication. 1064 // Shared entry point for floating point multiplication.
1138 Label do_fmul(&assembler), return_result(&assembler); 1065 Label do_fmul(this), return_result(this);
1139 Variable var_lhs_float64(&assembler, MachineRepresentation::kFloat64), 1066 Variable var_lhs_float64(this, MachineRepresentation::kFloat64),
1140 var_rhs_float64(&assembler, MachineRepresentation::kFloat64); 1067 var_rhs_float64(this, MachineRepresentation::kFloat64);
1141 1068
1142 Node* number_map = assembler.HeapNumberMapConstant(); 1069 Node* number_map = HeapNumberMapConstant();
1143 1070
1144 // We might need to loop one or two times due to ToNumber conversions. 1071 // We might need to loop one or two times due to ToNumber conversions.
1145 Variable var_lhs(&assembler, MachineRepresentation::kTagged), 1072 Variable var_lhs(this, MachineRepresentation::kTagged),
1146 var_rhs(&assembler, MachineRepresentation::kTagged), 1073 var_rhs(this, MachineRepresentation::kTagged),
1147 var_result(&assembler, MachineRepresentation::kTagged); 1074 var_result(this, MachineRepresentation::kTagged);
1148 Variable* loop_variables[] = {&var_lhs, &var_rhs}; 1075 Variable* loop_variables[] = {&var_lhs, &var_rhs};
1149 Label loop(&assembler, 2, loop_variables); 1076 Label loop(this, 2, loop_variables);
1150 var_lhs.Bind(left); 1077 var_lhs.Bind(left);
1151 var_rhs.Bind(right); 1078 var_rhs.Bind(right);
1152 assembler.Goto(&loop); 1079 Goto(&loop);
1153 assembler.Bind(&loop); 1080 Bind(&loop);
1154 { 1081 {
1155 Node* lhs = var_lhs.value(); 1082 Node* lhs = var_lhs.value();
1156 Node* rhs = var_rhs.value(); 1083 Node* rhs = var_rhs.value();
1157 1084
1158 Label lhs_is_smi(&assembler), lhs_is_not_smi(&assembler); 1085 Label lhs_is_smi(this), lhs_is_not_smi(this);
1159 assembler.Branch(assembler.TaggedIsSmi(lhs), &lhs_is_smi, &lhs_is_not_smi); 1086 Branch(TaggedIsSmi(lhs), &lhs_is_smi, &lhs_is_not_smi);
1160 1087
1161 assembler.Bind(&lhs_is_smi); 1088 Bind(&lhs_is_smi);
1162 { 1089 {
1163 Label rhs_is_smi(&assembler), rhs_is_not_smi(&assembler); 1090 Label rhs_is_smi(this), rhs_is_not_smi(this);
1164 assembler.Branch(assembler.TaggedIsSmi(rhs), &rhs_is_smi, 1091 Branch(TaggedIsSmi(rhs), &rhs_is_smi, &rhs_is_not_smi);
1165 &rhs_is_not_smi); 1092
1166 1093 Bind(&rhs_is_smi);
1167 assembler.Bind(&rhs_is_smi);
1168 { 1094 {
1169 // Both {lhs} and {rhs} are Smis. The result is not necessarily a smi, 1095 // Both {lhs} and {rhs} are Smis. The result is not necessarily a smi,
1170 // in case of overflow. 1096 // in case of overflow.
1171 var_result.Bind(assembler.SmiMul(lhs, rhs)); 1097 var_result.Bind(SmiMul(lhs, rhs));
1172 assembler.Goto(&return_result); 1098 Goto(&return_result);
1173 } 1099 }
1174 1100
1175 assembler.Bind(&rhs_is_not_smi); 1101 Bind(&rhs_is_not_smi);
1176 { 1102 {
1177 Node* rhs_map = assembler.LoadMap(rhs); 1103 Node* rhs_map = LoadMap(rhs);
1178 1104
1179 // Check if {rhs} is a HeapNumber. 1105 // Check if {rhs} is a HeapNumber.
1180 Label rhs_is_number(&assembler), 1106 Label rhs_is_number(this), rhs_is_not_number(this, Label::kDeferred);
1181 rhs_is_not_number(&assembler, Label::kDeferred); 1107 Branch(WordEqual(rhs_map, number_map), &rhs_is_number,
1182 assembler.Branch(assembler.WordEqual(rhs_map, number_map), 1108 &rhs_is_not_number);
1183 &rhs_is_number, &rhs_is_not_number); 1109
1184 1110 Bind(&rhs_is_number);
1185 assembler.Bind(&rhs_is_number);
1186 { 1111 {
1187 // Convert {lhs} to a double and multiply it with the value of {rhs}. 1112 // Convert {lhs} to a double and multiply it with the value of {rhs}.
1188 var_lhs_float64.Bind(assembler.SmiToFloat64(lhs)); 1113 var_lhs_float64.Bind(SmiToFloat64(lhs));
1189 var_rhs_float64.Bind(assembler.LoadHeapNumberValue(rhs)); 1114 var_rhs_float64.Bind(LoadHeapNumberValue(rhs));
1190 assembler.Goto(&do_fmul); 1115 Goto(&do_fmul);
1191 } 1116 }
1192 1117
1193 assembler.Bind(&rhs_is_not_number); 1118 Bind(&rhs_is_not_number);
1194 { 1119 {
1195 // Multiplication is commutative, swap {lhs} with {rhs} and loop. 1120 // Multiplication is commutative, swap {lhs} with {rhs} and loop.
1196 var_lhs.Bind(rhs); 1121 var_lhs.Bind(rhs);
1197 var_rhs.Bind(lhs); 1122 var_rhs.Bind(lhs);
1198 assembler.Goto(&loop); 1123 Goto(&loop);
1199 } 1124 }
1200 } 1125 }
1201 } 1126 }
1202 1127
1203 assembler.Bind(&lhs_is_not_smi); 1128 Bind(&lhs_is_not_smi);
1204 { 1129 {
1205 Node* lhs_map = assembler.LoadMap(lhs); 1130 Node* lhs_map = LoadMap(lhs);
1206 1131
1207 // Check if {lhs} is a HeapNumber. 1132 // Check if {lhs} is a HeapNumber.
1208 Label lhs_is_number(&assembler), 1133 Label lhs_is_number(this), lhs_is_not_number(this, Label::kDeferred);
1209 lhs_is_not_number(&assembler, Label::kDeferred); 1134 Branch(WordEqual(lhs_map, number_map), &lhs_is_number,
1210 assembler.Branch(assembler.WordEqual(lhs_map, number_map), &lhs_is_number, 1135 &lhs_is_not_number);
1211 &lhs_is_not_number); 1136
1212 1137 Bind(&lhs_is_number);
1213 assembler.Bind(&lhs_is_number);
1214 { 1138 {
1215 // Check if {rhs} is a Smi. 1139 // Check if {rhs} is a Smi.
1216 Label rhs_is_smi(&assembler), rhs_is_not_smi(&assembler); 1140 Label rhs_is_smi(this), rhs_is_not_smi(this);
1217 assembler.Branch(assembler.TaggedIsSmi(rhs), &rhs_is_smi, 1141 Branch(TaggedIsSmi(rhs), &rhs_is_smi, &rhs_is_not_smi);
1218 &rhs_is_not_smi); 1142
1219 1143 Bind(&rhs_is_smi);
1220 assembler.Bind(&rhs_is_smi);
1221 { 1144 {
1222 // Convert {rhs} to a double and multiply it with the value of {lhs}. 1145 // Convert {rhs} to a double and multiply it with the value of {lhs}.
1223 var_lhs_float64.Bind(assembler.LoadHeapNumberValue(lhs)); 1146 var_lhs_float64.Bind(LoadHeapNumberValue(lhs));
1224 var_rhs_float64.Bind(assembler.SmiToFloat64(rhs)); 1147 var_rhs_float64.Bind(SmiToFloat64(rhs));
1225 assembler.Goto(&do_fmul); 1148 Goto(&do_fmul);
1226 } 1149 }
1227 1150
1228 assembler.Bind(&rhs_is_not_smi); 1151 Bind(&rhs_is_not_smi);
1229 { 1152 {
1230 Node* rhs_map = assembler.LoadMap(rhs); 1153 Node* rhs_map = LoadMap(rhs);
1231 1154
1232 // Check if {rhs} is a HeapNumber. 1155 // Check if {rhs} is a HeapNumber.
1233 Label rhs_is_number(&assembler), 1156 Label rhs_is_number(this), rhs_is_not_number(this, Label::kDeferred);
1234 rhs_is_not_number(&assembler, Label::kDeferred); 1157 Branch(WordEqual(rhs_map, number_map), &rhs_is_number,
1235 assembler.Branch(assembler.WordEqual(rhs_map, number_map), 1158 &rhs_is_not_number);
1236 &rhs_is_number, &rhs_is_not_number); 1159
1237 1160 Bind(&rhs_is_number);
1238 assembler.Bind(&rhs_is_number);
1239 { 1161 {
1240 // Both {lhs} and {rhs} are HeapNumbers. Load their values and 1162 // Both {lhs} and {rhs} are HeapNumbers. Load their values and
1241 // multiply them. 1163 // multiply them.
1242 var_lhs_float64.Bind(assembler.LoadHeapNumberValue(lhs)); 1164 var_lhs_float64.Bind(LoadHeapNumberValue(lhs));
1243 var_rhs_float64.Bind(assembler.LoadHeapNumberValue(rhs)); 1165 var_rhs_float64.Bind(LoadHeapNumberValue(rhs));
1244 assembler.Goto(&do_fmul); 1166 Goto(&do_fmul);
1245 } 1167 }
1246 1168
1247 assembler.Bind(&rhs_is_not_number); 1169 Bind(&rhs_is_not_number);
1248 { 1170 {
1249 // Multiplication is commutative, swap {lhs} with {rhs} and loop. 1171 // Multiplication is commutative, swap {lhs} with {rhs} and loop.
1250 var_lhs.Bind(rhs); 1172 var_lhs.Bind(rhs);
1251 var_rhs.Bind(lhs); 1173 var_rhs.Bind(lhs);
1252 assembler.Goto(&loop); 1174 Goto(&loop);
1253 } 1175 }
1254 } 1176 }
1255 } 1177 }
1256 1178
1257 assembler.Bind(&lhs_is_not_number); 1179 Bind(&lhs_is_not_number);
1258 { 1180 {
1259 // Convert {lhs} to a Number and loop. 1181 // Convert {lhs} to a Number and loop.
1260 Callable callable = CodeFactory::NonNumberToNumber(assembler.isolate()); 1182 Callable callable = CodeFactory::NonNumberToNumber(isolate());
1261 var_lhs.Bind(assembler.CallStub(callable, context, lhs)); 1183 var_lhs.Bind(CallStub(callable, context, lhs));
1262 assembler.Goto(&loop); 1184 Goto(&loop);
1263 } 1185 }
1264 } 1186 }
1265 } 1187 }
1266 1188
1267 assembler.Bind(&do_fmul); 1189 Bind(&do_fmul);
1268 { 1190 {
1269 Node* value = 1191 Node* value = Float64Mul(var_lhs_float64.value(), var_rhs_float64.value());
1270 assembler.Float64Mul(var_lhs_float64.value(), var_rhs_float64.value()); 1192 Node* result = AllocateHeapNumberWithValue(value);
1271 Node* result = assembler.AllocateHeapNumberWithValue(value);
1272 var_result.Bind(result); 1193 var_result.Bind(result);
1273 assembler.Goto(&return_result); 1194 Goto(&return_result);
1274 } 1195 }
1275 1196
1276 assembler.Bind(&return_result); 1197 Bind(&return_result);
1277 assembler.Return(var_result.value()); 1198 Return(var_result.value());
1278 } 1199 }
1279 1200
1280 void Builtins::Generate_Divide(compiler::CodeAssemblerState* state) { 1201 TF_BUILTIN(Divide, CodeStubAssembler) {
1281 typedef CodeStubAssembler::Label Label; 1202 Node* left = Parameter(0);
1282 typedef compiler::Node Node; 1203 Node* right = Parameter(1);
1283 typedef CodeStubAssembler::Variable Variable; 1204 Node* context = Parameter(2);
1284 CodeStubAssembler assembler(state);
1285
1286 Node* left = assembler.Parameter(0);
1287 Node* right = assembler.Parameter(1);
1288 Node* context = assembler.Parameter(2);
1289 1205
1290 // Shared entry point for floating point division. 1206 // Shared entry point for floating point division.
1291 Label do_fdiv(&assembler), end(&assembler); 1207 Label do_fdiv(this), end(this);
1292 Variable var_dividend_float64(&assembler, MachineRepresentation::kFloat64), 1208 Variable var_dividend_float64(this, MachineRepresentation::kFloat64),
1293 var_divisor_float64(&assembler, MachineRepresentation::kFloat64); 1209 var_divisor_float64(this, MachineRepresentation::kFloat64);
1294 1210
1295 Node* number_map = assembler.HeapNumberMapConstant(); 1211 Node* number_map = HeapNumberMapConstant();
1296 1212
1297 // We might need to loop one or two times due to ToNumber conversions. 1213 // We might need to loop one or two times due to ToNumber conversions.
1298 Variable var_dividend(&assembler, MachineRepresentation::kTagged), 1214 Variable var_dividend(this, MachineRepresentation::kTagged),
1299 var_divisor(&assembler, MachineRepresentation::kTagged), 1215 var_divisor(this, MachineRepresentation::kTagged),
1300 var_result(&assembler, MachineRepresentation::kTagged); 1216 var_result(this, MachineRepresentation::kTagged);
1301 Variable* loop_variables[] = {&var_dividend, &var_divisor}; 1217 Variable* loop_variables[] = {&var_dividend, &var_divisor};
1302 Label loop(&assembler, 2, loop_variables); 1218 Label loop(this, 2, loop_variables);
1303 var_dividend.Bind(left); 1219 var_dividend.Bind(left);
1304 var_divisor.Bind(right); 1220 var_divisor.Bind(right);
1305 assembler.Goto(&loop); 1221 Goto(&loop);
1306 assembler.Bind(&loop); 1222 Bind(&loop);
1307 { 1223 {
1308 Node* dividend = var_dividend.value(); 1224 Node* dividend = var_dividend.value();
1309 Node* divisor = var_divisor.value(); 1225 Node* divisor = var_divisor.value();
1310 1226
1311 Label dividend_is_smi(&assembler), dividend_is_not_smi(&assembler); 1227 Label dividend_is_smi(this), dividend_is_not_smi(this);
1312 assembler.Branch(assembler.TaggedIsSmi(dividend), &dividend_is_smi, 1228 Branch(TaggedIsSmi(dividend), &dividend_is_smi, &dividend_is_not_smi);
1313 &dividend_is_not_smi); 1229
1314 1230 Bind(&dividend_is_smi);
1315 assembler.Bind(&dividend_is_smi);
1316 { 1231 {
1317 Label divisor_is_smi(&assembler), divisor_is_not_smi(&assembler); 1232 Label divisor_is_smi(this), divisor_is_not_smi(this);
1318 assembler.Branch(assembler.TaggedIsSmi(divisor), &divisor_is_smi, 1233 Branch(TaggedIsSmi(divisor), &divisor_is_smi, &divisor_is_not_smi);
1319 &divisor_is_not_smi); 1234
1320 1235 Bind(&divisor_is_smi);
1321 assembler.Bind(&divisor_is_smi); 1236 {
1322 { 1237 Label bailout(this);
1323 Label bailout(&assembler);
1324 1238
1325 // Do floating point division if {divisor} is zero. 1239 // Do floating point division if {divisor} is zero.
1326 assembler.GotoIf( 1240 GotoIf(WordEqual(divisor, IntPtrConstant(0)), &bailout);
1327 assembler.WordEqual(divisor, assembler.IntPtrConstant(0)),
1328 &bailout);
1329 1241
1330 // Do floating point division {dividend} is zero and {divisor} is 1242 // Do floating point division {dividend} is zero and {divisor} is
1331 // negative. 1243 // negative.
1332 Label dividend_is_zero(&assembler), dividend_is_not_zero(&assembler); 1244 Label dividend_is_zero(this), dividend_is_not_zero(this);
1333 assembler.Branch( 1245 Branch(WordEqual(dividend, IntPtrConstant(0)), &dividend_is_zero,
1334 assembler.WordEqual(dividend, assembler.IntPtrConstant(0)), 1246 &dividend_is_not_zero);
1335 &dividend_is_zero, &dividend_is_not_zero); 1247
1336 1248 Bind(&dividend_is_zero);
1337 assembler.Bind(&dividend_is_zero); 1249 {
1338 { 1250 GotoIf(IntPtrLessThan(divisor, IntPtrConstant(0)), &bailout);
1339 assembler.GotoIf( 1251 Goto(&dividend_is_not_zero);
1340 assembler.IntPtrLessThan(divisor, assembler.IntPtrConstant(0)), 1252 }
1341 &bailout); 1253 Bind(&dividend_is_not_zero);
1342 assembler.Goto(&dividend_is_not_zero); 1254
1343 } 1255 Node* untagged_divisor = SmiUntag(divisor);
1344 assembler.Bind(&dividend_is_not_zero); 1256 Node* untagged_dividend = SmiUntag(dividend);
1345
1346 Node* untagged_divisor = assembler.SmiUntag(divisor);
1347 Node* untagged_dividend = assembler.SmiUntag(dividend);
1348 1257
1349 // Do floating point division if {dividend} is kMinInt (or kMinInt - 1 1258 // Do floating point division if {dividend} is kMinInt (or kMinInt - 1
1350 // if the Smi size is 31) and {divisor} is -1. 1259 // if the Smi size is 31) and {divisor} is -1.
1351 Label divisor_is_minus_one(&assembler), 1260 Label divisor_is_minus_one(this), divisor_is_not_minus_one(this);
1352 divisor_is_not_minus_one(&assembler); 1261 Branch(Word32Equal(untagged_divisor, Int32Constant(-1)),
1353 assembler.Branch(assembler.Word32Equal(untagged_divisor, 1262 &divisor_is_minus_one, &divisor_is_not_minus_one);
1354 assembler.Int32Constant(-1)), 1263
1355 &divisor_is_minus_one, &divisor_is_not_minus_one); 1264 Bind(&divisor_is_minus_one);
1356 1265 {
1357 assembler.Bind(&divisor_is_minus_one); 1266 GotoIf(
1358 { 1267 Word32Equal(untagged_dividend,
1359 assembler.GotoIf( 1268 Int32Constant(kSmiValueSize == 32 ? kMinInt
1360 assembler.Word32Equal( 1269 : (kMinInt >> 1))),
1361 untagged_dividend,
1362 assembler.Int32Constant(
1363 kSmiValueSize == 32 ? kMinInt : (kMinInt >> 1))),
1364 &bailout); 1270 &bailout);
1365 assembler.Goto(&divisor_is_not_minus_one); 1271 Goto(&divisor_is_not_minus_one);
1366 } 1272 }
1367 assembler.Bind(&divisor_is_not_minus_one); 1273 Bind(&divisor_is_not_minus_one);
1368 1274
1369 // TODO(epertoso): consider adding a machine instruction that returns 1275 // TODO(epertoso): consider adding a machine instruction that returns
1370 // both the result and the remainder. 1276 // both the result and the remainder.
1371 Node* untagged_result = 1277 Node* untagged_result = Int32Div(untagged_dividend, untagged_divisor);
1372 assembler.Int32Div(untagged_dividend, untagged_divisor); 1278 Node* truncated = Int32Mul(untagged_result, untagged_divisor);
1373 Node* truncated = assembler.Int32Mul(untagged_result, untagged_divisor);
1374 // Do floating point division if the remainder is not 0. 1279 // Do floating point division if the remainder is not 0.
1375 assembler.GotoIf(assembler.Word32NotEqual(untagged_dividend, truncated), 1280 GotoIf(Word32NotEqual(untagged_dividend, truncated), &bailout);
1376 &bailout); 1281 var_result.Bind(SmiTag(untagged_result));
1377 var_result.Bind(assembler.SmiTag(untagged_result)); 1282 Goto(&end);
1378 assembler.Goto(&end);
1379 1283
1380 // Bailout: convert {dividend} and {divisor} to double and do double 1284 // Bailout: convert {dividend} and {divisor} to double and do double
1381 // division. 1285 // division.
1382 assembler.Bind(&bailout); 1286 Bind(&bailout);
1383 { 1287 {
1384 var_dividend_float64.Bind(assembler.SmiToFloat64(dividend)); 1288 var_dividend_float64.Bind(SmiToFloat64(dividend));
1385 var_divisor_float64.Bind(assembler.SmiToFloat64(divisor)); 1289 var_divisor_float64.Bind(SmiToFloat64(divisor));
1386 assembler.Goto(&do_fdiv); 1290 Goto(&do_fdiv);
1387 } 1291 }
1388 } 1292 }
1389 1293
1390 assembler.Bind(&divisor_is_not_smi); 1294 Bind(&divisor_is_not_smi);
1391 { 1295 {
1392 Node* divisor_map = assembler.LoadMap(divisor); 1296 Node* divisor_map = LoadMap(divisor);
1393 1297
1394 // Check if {divisor} is a HeapNumber. 1298 // Check if {divisor} is a HeapNumber.
1395 Label divisor_is_number(&assembler), 1299 Label divisor_is_number(this),
1396 divisor_is_not_number(&assembler, Label::kDeferred); 1300 divisor_is_not_number(this, Label::kDeferred);
1397 assembler.Branch(assembler.WordEqual(divisor_map, number_map), 1301 Branch(WordEqual(divisor_map, number_map), &divisor_is_number,
1398 &divisor_is_number, &divisor_is_not_number); 1302 &divisor_is_not_number);
1399 1303
1400 assembler.Bind(&divisor_is_number); 1304 Bind(&divisor_is_number);
1401 { 1305 {
1402 // Convert {dividend} to a double and divide it with the value of 1306 // Convert {dividend} to a double and divide it with the value of
1403 // {divisor}. 1307 // {divisor}.
1404 var_dividend_float64.Bind(assembler.SmiToFloat64(dividend)); 1308 var_dividend_float64.Bind(SmiToFloat64(dividend));
1405 var_divisor_float64.Bind(assembler.LoadHeapNumberValue(divisor)); 1309 var_divisor_float64.Bind(LoadHeapNumberValue(divisor));
1406 assembler.Goto(&do_fdiv); 1310 Goto(&do_fdiv);
1407 } 1311 }
1408 1312
1409 assembler.Bind(&divisor_is_not_number); 1313 Bind(&divisor_is_not_number);
1410 { 1314 {
1411 // Convert {divisor} to a number and loop. 1315 // Convert {divisor} to a number and loop.
1412 Callable callable = 1316 Callable callable = CodeFactory::NonNumberToNumber(isolate());
1413 CodeFactory::NonNumberToNumber(assembler.isolate()); 1317 var_divisor.Bind(CallStub(callable, context, divisor));
1414 var_divisor.Bind(assembler.CallStub(callable, context, divisor)); 1318 Goto(&loop);
1415 assembler.Goto(&loop); 1319 }
1416 } 1320 }
1417 } 1321 }
1418 } 1322
1419 1323 Bind(&dividend_is_not_smi);
1420 assembler.Bind(&dividend_is_not_smi);
1421 { 1324 {
1422 Node* dividend_map = assembler.LoadMap(dividend); 1325 Node* dividend_map = LoadMap(dividend);
1423 1326
1424 // Check if {dividend} is a HeapNumber. 1327 // Check if {dividend} is a HeapNumber.
1425 Label dividend_is_number(&assembler), 1328 Label dividend_is_number(this),
1426 dividend_is_not_number(&assembler, Label::kDeferred); 1329 dividend_is_not_number(this, Label::kDeferred);
1427 assembler.Branch(assembler.WordEqual(dividend_map, number_map), 1330 Branch(WordEqual(dividend_map, number_map), &dividend_is_number,
1428 &dividend_is_number, &dividend_is_not_number); 1331 &dividend_is_not_number);
1429 1332
1430 assembler.Bind(&dividend_is_number); 1333 Bind(&dividend_is_number);
1431 { 1334 {
1432 // Check if {divisor} is a Smi. 1335 // Check if {divisor} is a Smi.
1433 Label divisor_is_smi(&assembler), divisor_is_not_smi(&assembler); 1336 Label divisor_is_smi(this), divisor_is_not_smi(this);
1434 assembler.Branch(assembler.TaggedIsSmi(divisor), &divisor_is_smi, 1337 Branch(TaggedIsSmi(divisor), &divisor_is_smi, &divisor_is_not_smi);
1435 &divisor_is_not_smi); 1338
1436 1339 Bind(&divisor_is_smi);
1437 assembler.Bind(&divisor_is_smi);
1438 { 1340 {
1439 // Convert {divisor} to a double and use it for a floating point 1341 // Convert {divisor} to a double and use it for a floating point
1440 // division. 1342 // division.
1441 var_dividend_float64.Bind(assembler.LoadHeapNumberValue(dividend)); 1343 var_dividend_float64.Bind(LoadHeapNumberValue(dividend));
1442 var_divisor_float64.Bind(assembler.SmiToFloat64(divisor)); 1344 var_divisor_float64.Bind(SmiToFloat64(divisor));
1443 assembler.Goto(&do_fdiv); 1345 Goto(&do_fdiv);
1444 } 1346 }
1445 1347
1446 assembler.Bind(&divisor_is_not_smi); 1348 Bind(&divisor_is_not_smi);
1447 { 1349 {
1448 Node* divisor_map = assembler.LoadMap(divisor); 1350 Node* divisor_map = LoadMap(divisor);
1449 1351
1450 // Check if {divisor} is a HeapNumber. 1352 // Check if {divisor} is a HeapNumber.
1451 Label divisor_is_number(&assembler), 1353 Label divisor_is_number(this),
1452 divisor_is_not_number(&assembler, Label::kDeferred); 1354 divisor_is_not_number(this, Label::kDeferred);
1453 assembler.Branch(assembler.WordEqual(divisor_map, number_map), 1355 Branch(WordEqual(divisor_map, number_map), &divisor_is_number,
1454 &divisor_is_number, &divisor_is_not_number); 1356 &divisor_is_not_number);
1455 1357
1456 assembler.Bind(&divisor_is_number); 1358 Bind(&divisor_is_number);
1457 { 1359 {
1458 // Both {dividend} and {divisor} are HeapNumbers. Load their values 1360 // Both {dividend} and {divisor} are HeapNumbers. Load their values
1459 // and divide them. 1361 // and divide them.
1460 var_dividend_float64.Bind(assembler.LoadHeapNumberValue(dividend)); 1362 var_dividend_float64.Bind(LoadHeapNumberValue(dividend));
1461 var_divisor_float64.Bind(assembler.LoadHeapNumberValue(divisor)); 1363 var_divisor_float64.Bind(LoadHeapNumberValue(divisor));
1462 assembler.Goto(&do_fdiv); 1364 Goto(&do_fdiv);
1463 } 1365 }
1464 1366
1465 assembler.Bind(&divisor_is_not_number); 1367 Bind(&divisor_is_not_number);
1466 { 1368 {
1467 // Convert {divisor} to a number and loop. 1369 // Convert {divisor} to a number and loop.
1468 Callable callable = 1370 Callable callable = CodeFactory::NonNumberToNumber(isolate());
1469 CodeFactory::NonNumberToNumber(assembler.isolate()); 1371 var_divisor.Bind(CallStub(callable, context, divisor));
1470 var_divisor.Bind(assembler.CallStub(callable, context, divisor)); 1372 Goto(&loop);
1471 assembler.Goto(&loop);
1472 } 1373 }
1473 } 1374 }
1474 } 1375 }
1475 1376
1476 assembler.Bind(&dividend_is_not_number); 1377 Bind(&dividend_is_not_number);
1477 { 1378 {
1478 // Convert {dividend} to a Number and loop. 1379 // Convert {dividend} to a Number and loop.
1479 Callable callable = CodeFactory::NonNumberToNumber(assembler.isolate()); 1380 Callable callable = CodeFactory::NonNumberToNumber(isolate());
1480 var_dividend.Bind(assembler.CallStub(callable, context, dividend)); 1381 var_dividend.Bind(CallStub(callable, context, dividend));
1481 assembler.Goto(&loop); 1382 Goto(&loop);
1482 } 1383 }
1483 } 1384 }
1484 } 1385 }
1485 1386
1486 assembler.Bind(&do_fdiv); 1387 Bind(&do_fdiv);
1487 { 1388 {
1488 Node* value = assembler.Float64Div(var_dividend_float64.value(), 1389 Node* value =
1489 var_divisor_float64.value()); 1390 Float64Div(var_dividend_float64.value(), var_divisor_float64.value());
1490 var_result.Bind(assembler.AllocateHeapNumberWithValue(value)); 1391 var_result.Bind(AllocateHeapNumberWithValue(value));
1491 assembler.Goto(&end); 1392 Goto(&end);
1492 } 1393 }
1493 assembler.Bind(&end); 1394 Bind(&end);
1494 assembler.Return(var_result.value()); 1395 Return(var_result.value());
1495 } 1396 }
1496 1397
1497 void Builtins::Generate_Modulus(compiler::CodeAssemblerState* state) { 1398 TF_BUILTIN(Modulus, CodeStubAssembler) {
1498 typedef CodeStubAssembler::Label Label; 1399 Node* left = Parameter(0);
1499 typedef compiler::Node Node; 1400 Node* right = Parameter(1);
1500 typedef CodeStubAssembler::Variable Variable; 1401 Node* context = Parameter(2);
1501 CodeStubAssembler assembler(state); 1402
1502 1403 Variable var_result(this, MachineRepresentation::kTagged);
1503 Node* left = assembler.Parameter(0); 1404 Label return_result(this, &var_result);
1504 Node* right = assembler.Parameter(1);
1505 Node* context = assembler.Parameter(2);
1506
1507 Variable var_result(&assembler, MachineRepresentation::kTagged);
1508 Label return_result(&assembler, &var_result);
1509 1405
1510 // Shared entry point for floating point modulus. 1406 // Shared entry point for floating point modulus.
1511 Label do_fmod(&assembler); 1407 Label do_fmod(this);
1512 Variable var_dividend_float64(&assembler, MachineRepresentation::kFloat64), 1408 Variable var_dividend_float64(this, MachineRepresentation::kFloat64),
1513 var_divisor_float64(&assembler, MachineRepresentation::kFloat64); 1409 var_divisor_float64(this, MachineRepresentation::kFloat64);
1514 1410
1515 Node* number_map = assembler.HeapNumberMapConstant(); 1411 Node* number_map = HeapNumberMapConstant();
1516 1412
1517 // We might need to loop one or two times due to ToNumber conversions. 1413 // We might need to loop one or two times due to ToNumber conversions.
1518 Variable var_dividend(&assembler, MachineRepresentation::kTagged), 1414 Variable var_dividend(this, MachineRepresentation::kTagged),
1519 var_divisor(&assembler, MachineRepresentation::kTagged); 1415 var_divisor(this, MachineRepresentation::kTagged);
1520 Variable* loop_variables[] = {&var_dividend, &var_divisor}; 1416 Variable* loop_variables[] = {&var_dividend, &var_divisor};
1521 Label loop(&assembler, 2, loop_variables); 1417 Label loop(this, 2, loop_variables);
1522 var_dividend.Bind(left); 1418 var_dividend.Bind(left);
1523 var_divisor.Bind(right); 1419 var_divisor.Bind(right);
1524 assembler.Goto(&loop); 1420 Goto(&loop);
1525 assembler.Bind(&loop); 1421 Bind(&loop);
1526 { 1422 {
1527 Node* dividend = var_dividend.value(); 1423 Node* dividend = var_dividend.value();
1528 Node* divisor = var_divisor.value(); 1424 Node* divisor = var_divisor.value();
1529 1425
1530 Label dividend_is_smi(&assembler), dividend_is_not_smi(&assembler); 1426 Label dividend_is_smi(this), dividend_is_not_smi(this);
1531 assembler.Branch(assembler.TaggedIsSmi(dividend), &dividend_is_smi, 1427 Branch(TaggedIsSmi(dividend), &dividend_is_smi, &dividend_is_not_smi);
1532 &dividend_is_not_smi); 1428
1533 1429 Bind(&dividend_is_smi);
1534 assembler.Bind(&dividend_is_smi);
1535 { 1430 {
1536 Label dividend_is_not_zero(&assembler); 1431 Label dividend_is_not_zero(this);
1537 Label divisor_is_smi(&assembler), divisor_is_not_smi(&assembler); 1432 Label divisor_is_smi(this), divisor_is_not_smi(this);
1538 assembler.Branch(assembler.TaggedIsSmi(divisor), &divisor_is_smi, 1433 Branch(TaggedIsSmi(divisor), &divisor_is_smi, &divisor_is_not_smi);
1539 &divisor_is_not_smi); 1434
1540 1435 Bind(&divisor_is_smi);
1541 assembler.Bind(&divisor_is_smi);
1542 { 1436 {
1543 // Compute the modulus of two Smis. 1437 // Compute the modulus of two Smis.
1544 var_result.Bind(assembler.SmiMod(dividend, divisor)); 1438 var_result.Bind(SmiMod(dividend, divisor));
1545 assembler.Goto(&return_result); 1439 Goto(&return_result);
1546 } 1440 }
1547 1441
1548 assembler.Bind(&divisor_is_not_smi); 1442 Bind(&divisor_is_not_smi);
1549 { 1443 {
1550 Node* divisor_map = assembler.LoadMap(divisor); 1444 Node* divisor_map = LoadMap(divisor);
1551 1445
1552 // Check if {divisor} is a HeapNumber. 1446 // Check if {divisor} is a HeapNumber.
1553 Label divisor_is_number(&assembler), 1447 Label divisor_is_number(this),
1554 divisor_is_not_number(&assembler, Label::kDeferred); 1448 divisor_is_not_number(this, Label::kDeferred);
1555 assembler.Branch(assembler.WordEqual(divisor_map, number_map), 1449 Branch(WordEqual(divisor_map, number_map), &divisor_is_number,
1556 &divisor_is_number, &divisor_is_not_number); 1450 &divisor_is_not_number);
1557 1451
1558 assembler.Bind(&divisor_is_number); 1452 Bind(&divisor_is_number);
1559 { 1453 {
1560 // Convert {dividend} to a double and compute its modulus with the 1454 // Convert {dividend} to a double and compute its modulus with the
1561 // value of {dividend}. 1455 // value of {dividend}.
1562 var_dividend_float64.Bind(assembler.SmiToFloat64(dividend)); 1456 var_dividend_float64.Bind(SmiToFloat64(dividend));
1563 var_divisor_float64.Bind(assembler.LoadHeapNumberValue(divisor)); 1457 var_divisor_float64.Bind(LoadHeapNumberValue(divisor));
1564 assembler.Goto(&do_fmod); 1458 Goto(&do_fmod);
1565 } 1459 }
1566 1460
1567 assembler.Bind(&divisor_is_not_number); 1461 Bind(&divisor_is_not_number);
1568 { 1462 {
1569 // Convert {divisor} to a number and loop. 1463 // Convert {divisor} to a number and loop.
1570 Callable callable = 1464 Callable callable = CodeFactory::NonNumberToNumber(isolate());
1571 CodeFactory::NonNumberToNumber(assembler.isolate()); 1465 var_divisor.Bind(CallStub(callable, context, divisor));
1572 var_divisor.Bind(assembler.CallStub(callable, context, divisor)); 1466 Goto(&loop);
1573 assembler.Goto(&loop); 1467 }
1574 } 1468 }
1575 } 1469 }
1576 } 1470
1577 1471 Bind(&dividend_is_not_smi);
1578 assembler.Bind(&dividend_is_not_smi);
1579 { 1472 {
1580 Node* dividend_map = assembler.LoadMap(dividend); 1473 Node* dividend_map = LoadMap(dividend);
1581 1474
1582 // Check if {dividend} is a HeapNumber. 1475 // Check if {dividend} is a HeapNumber.
1583 Label dividend_is_number(&assembler), 1476 Label dividend_is_number(this),
1584 dividend_is_not_number(&assembler, Label::kDeferred); 1477 dividend_is_not_number(this, Label::kDeferred);
1585 assembler.Branch(assembler.WordEqual(dividend_map, number_map), 1478 Branch(WordEqual(dividend_map, number_map), &dividend_is_number,
1586 &dividend_is_number, &dividend_is_not_number); 1479 &dividend_is_not_number);
1587 1480
1588 assembler.Bind(&dividend_is_number); 1481 Bind(&dividend_is_number);
1589 { 1482 {
1590 // Check if {divisor} is a Smi. 1483 // Check if {divisor} is a Smi.
1591 Label divisor_is_smi(&assembler), divisor_is_not_smi(&assembler); 1484 Label divisor_is_smi(this), divisor_is_not_smi(this);
1592 assembler.Branch(assembler.TaggedIsSmi(divisor), &divisor_is_smi, 1485 Branch(TaggedIsSmi(divisor), &divisor_is_smi, &divisor_is_not_smi);
1593 &divisor_is_not_smi); 1486
1594 1487 Bind(&divisor_is_smi);
1595 assembler.Bind(&divisor_is_smi);
1596 { 1488 {
1597 // Convert {divisor} to a double and compute {dividend}'s modulus with 1489 // Convert {divisor} to a double and compute {dividend}'s modulus with
1598 // it. 1490 // it.
1599 var_dividend_float64.Bind(assembler.LoadHeapNumberValue(dividend)); 1491 var_dividend_float64.Bind(LoadHeapNumberValue(dividend));
1600 var_divisor_float64.Bind(assembler.SmiToFloat64(divisor)); 1492 var_divisor_float64.Bind(SmiToFloat64(divisor));
1601 assembler.Goto(&do_fmod); 1493 Goto(&do_fmod);
1602 } 1494 }
1603 1495
1604 assembler.Bind(&divisor_is_not_smi); 1496 Bind(&divisor_is_not_smi);
1605 { 1497 {
1606 Node* divisor_map = assembler.LoadMap(divisor); 1498 Node* divisor_map = LoadMap(divisor);
1607 1499
1608 // Check if {divisor} is a HeapNumber. 1500 // Check if {divisor} is a HeapNumber.
1609 Label divisor_is_number(&assembler), 1501 Label divisor_is_number(this),
1610 divisor_is_not_number(&assembler, Label::kDeferred); 1502 divisor_is_not_number(this, Label::kDeferred);
1611 assembler.Branch(assembler.WordEqual(divisor_map, number_map), 1503 Branch(WordEqual(divisor_map, number_map), &divisor_is_number,
1612 &divisor_is_number, &divisor_is_not_number); 1504 &divisor_is_not_number);
1613 1505
1614 assembler.Bind(&divisor_is_number); 1506 Bind(&divisor_is_number);
1615 { 1507 {
1616 // Both {dividend} and {divisor} are HeapNumbers. Load their values 1508 // Both {dividend} and {divisor} are HeapNumbers. Load their values
1617 // and compute their modulus. 1509 // and compute their modulus.
1618 var_dividend_float64.Bind(assembler.LoadHeapNumberValue(dividend)); 1510 var_dividend_float64.Bind(LoadHeapNumberValue(dividend));
1619 var_divisor_float64.Bind(assembler.LoadHeapNumberValue(divisor)); 1511 var_divisor_float64.Bind(LoadHeapNumberValue(divisor));
1620 assembler.Goto(&do_fmod); 1512 Goto(&do_fmod);
1621 } 1513 }
1622 1514
1623 assembler.Bind(&divisor_is_not_number); 1515 Bind(&divisor_is_not_number);
1624 { 1516 {
1625 // Convert {divisor} to a number and loop. 1517 // Convert {divisor} to a number and loop.
1626 Callable callable = 1518 Callable callable = CodeFactory::NonNumberToNumber(isolate());
1627 CodeFactory::NonNumberToNumber(assembler.isolate()); 1519 var_divisor.Bind(CallStub(callable, context, divisor));
1628 var_divisor.Bind(assembler.CallStub(callable, context, divisor)); 1520 Goto(&loop);
1629 assembler.Goto(&loop);
1630 } 1521 }
1631 } 1522 }
1632 } 1523 }
1633 1524
1634 assembler.Bind(&dividend_is_not_number); 1525 Bind(&dividend_is_not_number);
1635 { 1526 {
1636 // Convert {dividend} to a Number and loop. 1527 // Convert {dividend} to a Number and loop.
1637 Callable callable = CodeFactory::NonNumberToNumber(assembler.isolate()); 1528 Callable callable = CodeFactory::NonNumberToNumber(isolate());
1638 var_dividend.Bind(assembler.CallStub(callable, context, dividend)); 1529 var_dividend.Bind(CallStub(callable, context, dividend));
1639 assembler.Goto(&loop); 1530 Goto(&loop);
1640 } 1531 }
1641 } 1532 }
1642 } 1533 }
1643 1534
1644 assembler.Bind(&do_fmod); 1535 Bind(&do_fmod);
1645 { 1536 {
1646 Node* value = assembler.Float64Mod(var_dividend_float64.value(), 1537 Node* value =
1647 var_divisor_float64.value()); 1538 Float64Mod(var_dividend_float64.value(), var_divisor_float64.value());
1648 var_result.Bind(assembler.AllocateHeapNumberWithValue(value)); 1539 var_result.Bind(AllocateHeapNumberWithValue(value));
1649 assembler.Goto(&return_result); 1540 Goto(&return_result);
1650 } 1541 }
1651 1542
1652 assembler.Bind(&return_result); 1543 Bind(&return_result);
1653 assembler.Return(var_result.value()); 1544 Return(var_result.value());
1654 } 1545 }
1655 1546
1656 void Builtins::Generate_ShiftLeft(compiler::CodeAssemblerState* state) { 1547 TF_BUILTIN(ShiftLeft, NumberBuiltinsAssembler) {
1657 using compiler::Node; 1548 BitwiseShiftOp([this](Node* lhs, Node* shift_count) {
1658 CodeStubAssembler assembler(state); 1549 return Word32Shl(lhs, shift_count);
1659 1550 });
1660 Node* left = assembler.Parameter(0); 1551 }
1661 Node* right = assembler.Parameter(1); 1552
1662 Node* context = assembler.Parameter(2); 1553 TF_BUILTIN(ShiftRight, NumberBuiltinsAssembler) {
1663 1554 BitwiseShiftOp([this](Node* lhs, Node* shift_count) {
1664 Node* lhs_value = assembler.TruncateTaggedToWord32(context, left); 1555 return Word32Sar(lhs, shift_count);
1665 Node* rhs_value = assembler.TruncateTaggedToWord32(context, right); 1556 });
1666 Node* shift_count = 1557 }
1667 assembler.Word32And(rhs_value, assembler.Int32Constant(0x1f)); 1558
1668 Node* value = assembler.Word32Shl(lhs_value, shift_count); 1559 TF_BUILTIN(ShiftRightLogical, NumberBuiltinsAssembler) {
1669 Node* result = assembler.ChangeInt32ToTagged(value); 1560 BitwiseShiftOp<kUnsigned>([this](Node* lhs, Node* shift_count) {
1670 assembler.Return(result); 1561 return Word32Shr(lhs, shift_count);
1671 } 1562 });
1672 1563 }
1673 void Builtins::Generate_ShiftRight(compiler::CodeAssemblerState* state) { 1564
1674 using compiler::Node; 1565 TF_BUILTIN(BitwiseAnd, NumberBuiltinsAssembler) {
1675 CodeStubAssembler assembler(state); 1566 BitwiseOp([this](Node* lhs, Node* rhs) { return Word32And(lhs, rhs); });
1676 1567 }
1677 Node* left = assembler.Parameter(0); 1568
1678 Node* right = assembler.Parameter(1); 1569 TF_BUILTIN(BitwiseOr, NumberBuiltinsAssembler) {
1679 Node* context = assembler.Parameter(2); 1570 BitwiseOp([this](Node* lhs, Node* rhs) { return Word32Or(lhs, rhs); });
1680 1571 }
1681 Node* lhs_value = assembler.TruncateTaggedToWord32(context, left); 1572
1682 Node* rhs_value = assembler.TruncateTaggedToWord32(context, right); 1573 TF_BUILTIN(BitwiseXor, NumberBuiltinsAssembler) {
1683 Node* shift_count = 1574 BitwiseOp([this](Node* lhs, Node* rhs) { return Word32Xor(lhs, rhs); });
1684 assembler.Word32And(rhs_value, assembler.Int32Constant(0x1f)); 1575 }
1685 Node* value = assembler.Word32Sar(lhs_value, shift_count); 1576
1686 Node* result = assembler.ChangeInt32ToTagged(value); 1577 TF_BUILTIN(LessThan, NumberBuiltinsAssembler) {
1687 assembler.Return(result); 1578 RelationalComparisonBuiltin(kLessThan);
1688 } 1579 }
1689 1580
1690 void Builtins::Generate_ShiftRightLogical(compiler::CodeAssemblerState* state) { 1581 TF_BUILTIN(LessThanOrEqual, NumberBuiltinsAssembler) {
1691 using compiler::Node; 1582 RelationalComparisonBuiltin(kLessThanOrEqual);
1692 CodeStubAssembler assembler(state); 1583 }
1693 1584
1694 Node* left = assembler.Parameter(0); 1585 TF_BUILTIN(GreaterThan, NumberBuiltinsAssembler) {
1695 Node* right = assembler.Parameter(1); 1586 RelationalComparisonBuiltin(kGreaterThan);
1696 Node* context = assembler.Parameter(2); 1587 }
1697 1588
1698 Node* lhs_value = assembler.TruncateTaggedToWord32(context, left); 1589 TF_BUILTIN(GreaterThanOrEqual, NumberBuiltinsAssembler) {
1699 Node* rhs_value = assembler.TruncateTaggedToWord32(context, right); 1590 RelationalComparisonBuiltin(kGreaterThanOrEqual);
1700 Node* shift_count = 1591 }
1701 assembler.Word32And(rhs_value, assembler.Int32Constant(0x1f)); 1592
1702 Node* value = assembler.Word32Shr(lhs_value, shift_count); 1593 TF_BUILTIN(Equal, CodeStubAssembler) {
1703 Node* result = assembler.ChangeUint32ToTagged(value); 1594 Node* lhs = Parameter(0);
1704 assembler.Return(result); 1595 Node* rhs = Parameter(1);
1705 } 1596 Node* context = Parameter(2);
1706 1597
1707 void Builtins::Generate_BitwiseAnd(compiler::CodeAssemblerState* state) { 1598 Return(Equal(kDontNegateResult, lhs, rhs, context));
1708 CodeStubAssembler assembler(state); 1599 }
1709 using compiler::Node; 1600
1710 1601 TF_BUILTIN(NotEqual, CodeStubAssembler) {
1711 Node* left = assembler.Parameter(0); 1602 Node* lhs = Parameter(0);
1712 Node* right = assembler.Parameter(1); 1603 Node* rhs = Parameter(1);
1713 Node* context = assembler.Parameter(2); 1604 Node* context = Parameter(2);
1714 1605
1715 Node* lhs_value = assembler.TruncateTaggedToWord32(context, left); 1606 Return(Equal(kNegateResult, lhs, rhs, context));
1716 Node* rhs_value = assembler.TruncateTaggedToWord32(context, right); 1607 }
1717 Node* value = assembler.Word32And(lhs_value, rhs_value); 1608
1718 Node* result = assembler.ChangeInt32ToTagged(value); 1609 TF_BUILTIN(StrictEqual, CodeStubAssembler) {
1719 assembler.Return(result); 1610 Node* lhs = Parameter(0);
1720 } 1611 Node* rhs = Parameter(1);
1721 1612 Node* context = Parameter(2);
1722 void Builtins::Generate_BitwiseOr(compiler::CodeAssemblerState* state) { 1613
1723 CodeStubAssembler assembler(state); 1614 Return(StrictEqual(kDontNegateResult, lhs, rhs, context));
1724 using compiler::Node; 1615 }
1725 1616
1726 Node* left = assembler.Parameter(0); 1617 TF_BUILTIN(StrictNotEqual, CodeStubAssembler) {
1727 Node* right = assembler.Parameter(1); 1618 Node* lhs = Parameter(0);
1728 Node* context = assembler.Parameter(2); 1619 Node* rhs = Parameter(1);
1729 1620 Node* context = Parameter(2);
1730 Node* lhs_value = assembler.TruncateTaggedToWord32(context, left); 1621
1731 Node* rhs_value = assembler.TruncateTaggedToWord32(context, right); 1622 Return(StrictEqual(kNegateResult, lhs, rhs, context));
1732 Node* value = assembler.Word32Or(lhs_value, rhs_value);
1733 Node* result = assembler.ChangeInt32ToTagged(value);
1734 assembler.Return(result);
1735 }
1736
1737 void Builtins::Generate_BitwiseXor(compiler::CodeAssemblerState* state) {
1738 CodeStubAssembler assembler(state);
1739 using compiler::Node;
1740
1741 Node* left = assembler.Parameter(0);
1742 Node* right = assembler.Parameter(1);
1743 Node* context = assembler.Parameter(2);
1744
1745 Node* lhs_value = assembler.TruncateTaggedToWord32(context, left);
1746 Node* rhs_value = assembler.TruncateTaggedToWord32(context, right);
1747 Node* value = assembler.Word32Xor(lhs_value, rhs_value);
1748 Node* result = assembler.ChangeInt32ToTagged(value);
1749 assembler.Return(result);
1750 }
1751
1752 void Builtins::Generate_LessThan(compiler::CodeAssemblerState* state) {
1753 CodeStubAssembler assembler(state);
1754 compiler::Node* lhs = assembler.Parameter(0);
1755 compiler::Node* rhs = assembler.Parameter(1);
1756 compiler::Node* context = assembler.Parameter(2);
1757
1758 assembler.Return(assembler.RelationalComparison(CodeStubAssembler::kLessThan,
1759 lhs, rhs, context));
1760 }
1761
1762 void Builtins::Generate_LessThanOrEqual(compiler::CodeAssemblerState* state) {
1763 CodeStubAssembler assembler(state);
1764 compiler::Node* lhs = assembler.Parameter(0);
1765 compiler::Node* rhs = assembler.Parameter(1);
1766 compiler::Node* context = assembler.Parameter(2);
1767
1768 assembler.Return(assembler.RelationalComparison(
1769 CodeStubAssembler::kLessThanOrEqual, lhs, rhs, context));
1770 }
1771
1772 void Builtins::Generate_GreaterThan(compiler::CodeAssemblerState* state) {
1773 CodeStubAssembler assembler(state);
1774 compiler::Node* lhs = assembler.Parameter(0);
1775 compiler::Node* rhs = assembler.Parameter(1);
1776 compiler::Node* context = assembler.Parameter(2);
1777
1778 assembler.Return(assembler.RelationalComparison(
1779 CodeStubAssembler::kGreaterThan, lhs, rhs, context));
1780 }
1781
1782 void Builtins::Generate_GreaterThanOrEqual(
1783 compiler::CodeAssemblerState* state) {
1784 CodeStubAssembler assembler(state);
1785 compiler::Node* lhs = assembler.Parameter(0);
1786 compiler::Node* rhs = assembler.Parameter(1);
1787 compiler::Node* context = assembler.Parameter(2);
1788
1789 assembler.Return(assembler.RelationalComparison(
1790 CodeStubAssembler::kGreaterThanOrEqual, lhs, rhs, context));
1791 }
1792
1793 void Builtins::Generate_Equal(compiler::CodeAssemblerState* state) {
1794 CodeStubAssembler assembler(state);
1795 compiler::Node* lhs = assembler.Parameter(0);
1796 compiler::Node* rhs = assembler.Parameter(1);
1797 compiler::Node* context = assembler.Parameter(2);
1798
1799 assembler.Return(
1800 assembler.Equal(CodeStubAssembler::kDontNegateResult, lhs, rhs, context));
1801 }
1802
1803 void Builtins::Generate_NotEqual(compiler::CodeAssemblerState* state) {
1804 CodeStubAssembler assembler(state);
1805 compiler::Node* lhs = assembler.Parameter(0);
1806 compiler::Node* rhs = assembler.Parameter(1);
1807 compiler::Node* context = assembler.Parameter(2);
1808
1809 assembler.Return(
1810 assembler.Equal(CodeStubAssembler::kNegateResult, lhs, rhs, context));
1811 }
1812
1813 void Builtins::Generate_StrictEqual(compiler::CodeAssemblerState* state) {
1814 CodeStubAssembler assembler(state);
1815 compiler::Node* lhs = assembler.Parameter(0);
1816 compiler::Node* rhs = assembler.Parameter(1);
1817 compiler::Node* context = assembler.Parameter(2);
1818
1819 assembler.Return(assembler.StrictEqual(CodeStubAssembler::kDontNegateResult,
1820 lhs, rhs, context));
1821 }
1822
1823 void Builtins::Generate_StrictNotEqual(compiler::CodeAssemblerState* state) {
1824 CodeStubAssembler assembler(state);
1825 compiler::Node* lhs = assembler.Parameter(0);
1826 compiler::Node* rhs = assembler.Parameter(1);
1827 compiler::Node* context = assembler.Parameter(2);
1828
1829 assembler.Return(assembler.StrictEqual(CodeStubAssembler::kNegateResult, lhs,
1830 rhs, context));
1831 } 1623 }
1832 1624
1833 } // namespace internal 1625 } // namespace internal
1834 } // namespace v8 1626 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/builtins/builtins-utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698