OLD | NEW |
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 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 assembler->Float64Abs(integer), | 143 assembler->Float64Abs(integer), |
144 assembler->Float64Constant(kMaxSafeInteger), &return_true, &return_false); | 144 assembler->Float64Constant(kMaxSafeInteger), &return_true, &return_false); |
145 | 145 |
146 assembler->Bind(&return_true); | 146 assembler->Bind(&return_true); |
147 assembler->Return(assembler->BooleanConstant(true)); | 147 assembler->Return(assembler->BooleanConstant(true)); |
148 | 148 |
149 assembler->Bind(&return_false); | 149 assembler->Bind(&return_false); |
150 assembler->Return(assembler->BooleanConstant(false)); | 150 assembler->Return(assembler->BooleanConstant(false)); |
151 } | 151 } |
152 | 152 |
| 153 // ES6 section 20.1.2.12 Number.parseFloat ( string ) |
| 154 void Builtins::Generate_NumberParseFloat(CodeStubAssembler* assembler) { |
| 155 typedef CodeStubAssembler::Label Label; |
| 156 typedef compiler::Node Node; |
| 157 typedef CodeStubAssembler::Variable Variable; |
| 158 |
| 159 Node* context = assembler->Parameter(4); |
| 160 |
| 161 // We might need to loop once for ToString conversion. |
| 162 Variable var_input(assembler, MachineRepresentation::kTagged); |
| 163 Label loop(assembler, &var_input); |
| 164 var_input.Bind(assembler->Parameter(1)); |
| 165 assembler->Goto(&loop); |
| 166 assembler->Bind(&loop); |
| 167 { |
| 168 // Load the current {input} value. |
| 169 Node* input = var_input.value(); |
| 170 |
| 171 // Check if the {input} is a HeapObject or a Smi. |
| 172 Label if_inputissmi(assembler), if_inputisnotsmi(assembler); |
| 173 assembler->Branch(assembler->WordIsSmi(input), &if_inputissmi, |
| 174 &if_inputisnotsmi); |
| 175 |
| 176 assembler->Bind(&if_inputissmi); |
| 177 { |
| 178 // The {input} is already a Number, no need to do anything. |
| 179 assembler->Return(input); |
| 180 } |
| 181 |
| 182 assembler->Bind(&if_inputisnotsmi); |
| 183 { |
| 184 // The {input} is a HeapObject, check if it's already a String. |
| 185 Label if_inputisstring(assembler), if_inputisnotstring(assembler); |
| 186 Node* input_map = assembler->LoadMap(input); |
| 187 Node* input_instance_type = assembler->LoadMapInstanceType(input_map); |
| 188 assembler->Branch(assembler->IsStringInstanceType(input_instance_type), |
| 189 &if_inputisstring, &if_inputisnotstring); |
| 190 |
| 191 assembler->Bind(&if_inputisstring); |
| 192 { |
| 193 // The {input} is already a String, check if {input} contains |
| 194 // a cached array index. |
| 195 Label if_inputcached(assembler), if_inputnotcached(assembler); |
| 196 Node* input_hash = assembler->LoadNameHashField(input); |
| 197 Node* input_bit = assembler->Word32And( |
| 198 input_hash, |
| 199 assembler->Int32Constant(String::kContainsCachedArrayIndexMask)); |
| 200 assembler->Branch( |
| 201 assembler->Word32Equal(input_bit, assembler->Int32Constant(0)), |
| 202 &if_inputcached, &if_inputnotcached); |
| 203 |
| 204 assembler->Bind(&if_inputcached); |
| 205 { |
| 206 // Just return the {input}s cached array index. |
| 207 Node* input_array_index = |
| 208 assembler->BitFieldDecodeWord<String::ArrayIndexValueBits>( |
| 209 input_hash); |
| 210 assembler->Return(assembler->SmiTag(input_array_index)); |
| 211 } |
| 212 |
| 213 assembler->Bind(&if_inputnotcached); |
| 214 { |
| 215 // Need to fall back to the runtime to convert {input} to double. |
| 216 assembler->Return(assembler->CallRuntime(Runtime::kStringParseFloat, |
| 217 context, input)); |
| 218 } |
| 219 } |
| 220 |
| 221 assembler->Bind(&if_inputisnotstring); |
| 222 { |
| 223 // The {input} is neither a String nor a Smi, check for HeapNumber. |
| 224 Label if_inputisnumber(assembler), |
| 225 if_inputisnotnumber(assembler, Label::kDeferred); |
| 226 assembler->Branch( |
| 227 assembler->WordEqual(input_map, assembler->HeapNumberMapConstant()), |
| 228 &if_inputisnumber, &if_inputisnotnumber); |
| 229 |
| 230 assembler->Bind(&if_inputisnumber); |
| 231 { |
| 232 // The {input} is already a Number, take care of -0. |
| 233 Label if_inputiszero(assembler), if_inputisnotzero(assembler); |
| 234 Node* input_value = assembler->LoadHeapNumberValue(input); |
| 235 assembler->Branch(assembler->Float64Equal( |
| 236 input_value, assembler->Float64Constant(0.0)), |
| 237 &if_inputiszero, &if_inputisnotzero); |
| 238 |
| 239 assembler->Bind(&if_inputiszero); |
| 240 assembler->Return(assembler->SmiConstant(0)); |
| 241 |
| 242 assembler->Bind(&if_inputisnotzero); |
| 243 assembler->Return(input); |
| 244 } |
| 245 |
| 246 assembler->Bind(&if_inputisnotnumber); |
| 247 { |
| 248 // Need to convert the {input} to String first. |
| 249 // TODO(bmeurer): This could be more efficient if necessary. |
| 250 Callable callable = CodeFactory::ToString(assembler->isolate()); |
| 251 var_input.Bind(assembler->CallStub(callable, context, input)); |
| 252 assembler->Goto(&loop); |
| 253 } |
| 254 } |
| 255 } |
| 256 } |
| 257 } |
| 258 |
153 // ES6 section 20.1.3.2 Number.prototype.toExponential ( fractionDigits ) | 259 // ES6 section 20.1.3.2 Number.prototype.toExponential ( fractionDigits ) |
154 BUILTIN(NumberPrototypeToExponential) { | 260 BUILTIN(NumberPrototypeToExponential) { |
155 HandleScope scope(isolate); | 261 HandleScope scope(isolate); |
156 Handle<Object> value = args.at<Object>(0); | 262 Handle<Object> value = args.at<Object>(0); |
157 Handle<Object> fraction_digits = args.atOrUndefined(isolate, 1); | 263 Handle<Object> fraction_digits = args.atOrUndefined(isolate, 1); |
158 | 264 |
159 // Unwrap the receiver {value}. | 265 // Unwrap the receiver {value}. |
160 if (value->IsJSValue()) { | 266 if (value->IsJSValue()) { |
161 value = handle(Handle<JSValue>::cast(value)->value(), isolate); | 267 value = handle(Handle<JSValue>::cast(value)->value(), isolate); |
162 } | 268 } |
(...skipping 1432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1595 compiler::Node* lhs = assembler->Parameter(0); | 1701 compiler::Node* lhs = assembler->Parameter(0); |
1596 compiler::Node* rhs = assembler->Parameter(1); | 1702 compiler::Node* rhs = assembler->Parameter(1); |
1597 compiler::Node* context = assembler->Parameter(2); | 1703 compiler::Node* context = assembler->Parameter(2); |
1598 | 1704 |
1599 assembler->Return(assembler->StrictEqual(CodeStubAssembler::kNegateResult, | 1705 assembler->Return(assembler->StrictEqual(CodeStubAssembler::kNegateResult, |
1600 lhs, rhs, context)); | 1706 lhs, rhs, context)); |
1601 } | 1707 } |
1602 | 1708 |
1603 } // namespace internal | 1709 } // namespace internal |
1604 } // namespace v8 | 1710 } // namespace v8 |
OLD | NEW |