OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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.h" | 5 #include "src/builtins.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/api-arguments.h" | 8 #include "src/api-arguments.h" |
9 #include "src/api-natives.h" | 9 #include "src/api-natives.h" |
10 #include "src/base/once.h" | 10 #include "src/base/once.h" |
(...skipping 4147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4158 // ES6 19.1.3.6 Object.prototype.toString | 4158 // ES6 19.1.3.6 Object.prototype.toString |
4159 BUILTIN(ObjectProtoToString) { | 4159 BUILTIN(ObjectProtoToString) { |
4160 HandleScope scope(isolate); | 4160 HandleScope scope(isolate); |
4161 Handle<Object> object = args.at<Object>(0); | 4161 Handle<Object> object = args.at<Object>(0); |
4162 Handle<String> result; | 4162 Handle<String> result; |
4163 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 4163 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
4164 isolate, result, Object::ObjectProtoToString(isolate, object)); | 4164 isolate, result, Object::ObjectProtoToString(isolate, object)); |
4165 return *result; | 4165 return *result; |
4166 } | 4166 } |
4167 | 4167 |
| 4168 // ----------------------------------------------------------------------------- |
| 4169 // ES6 section 21.1 String Objects |
| 4170 |
| 4171 // ES6 section 21.1.3.1 String.prototype.charAt ( pos ) |
| 4172 void Builtins::Generate_StringPrototypeCharAt( |
| 4173 compiler::CodeStubAssembler* assembler) { |
| 4174 typedef compiler::CodeStubAssembler::Label Label; |
| 4175 typedef compiler::Node Node; |
| 4176 typedef compiler::CodeStubAssembler::Variable Variable; |
| 4177 |
| 4178 Node* receiver = assembler->Parameter(0); |
| 4179 Node* position = assembler->Parameter(1); |
| 4180 Node* context = assembler->Parameter(4); |
| 4181 |
| 4182 // Check that {receiver} is coercible to Object and convert it to a String. |
| 4183 receiver = |
| 4184 assembler->ToThisString(context, receiver, "String.prototype.charAt"); |
| 4185 |
| 4186 // Convert the {position} to a Smi and check that it's in bounds of the |
| 4187 // {receiver}. |
| 4188 // TODO(bmeurer): Find an abstraction for this! |
| 4189 { |
| 4190 // Check if the {position} is already a Smi. |
| 4191 Variable var_position(assembler, MachineRepresentation::kTagged); |
| 4192 var_position.Bind(position); |
| 4193 Label if_positionissmi(assembler), |
| 4194 if_positionisnotsmi(assembler, Label::kDeferred); |
| 4195 assembler->Branch(assembler->WordIsSmi(position), &if_positionissmi, |
| 4196 &if_positionisnotsmi); |
| 4197 assembler->Bind(&if_positionisnotsmi); |
| 4198 { |
| 4199 // Convert the {position} to an Integer via the ToIntegerStub. |
| 4200 Callable callable = CodeFactory::ToInteger(assembler->isolate()); |
| 4201 Node* index = assembler->CallStub(callable, context, position); |
| 4202 |
| 4203 // Check if the resulting {index} is now a Smi. |
| 4204 Label if_indexissmi(assembler, Label::kDeferred), |
| 4205 if_indexisnotsmi(assembler, Label::kDeferred); |
| 4206 assembler->Branch(assembler->WordIsSmi(index), &if_indexissmi, |
| 4207 &if_indexisnotsmi); |
| 4208 |
| 4209 assembler->Bind(&if_indexissmi); |
| 4210 { |
| 4211 var_position.Bind(index); |
| 4212 assembler->Goto(&if_positionissmi); |
| 4213 } |
| 4214 |
| 4215 assembler->Bind(&if_indexisnotsmi); |
| 4216 { |
| 4217 // The ToIntegerStub canonicalizes everything in Smi range to Smi |
| 4218 // representation, so any HeapNumber returned is not in Smi range. |
| 4219 // The only exception here is -0.0, which we treat as 0. |
| 4220 Node* index_value = assembler->LoadHeapNumberValue(index); |
| 4221 Label if_indexiszero(assembler, Label::kDeferred), |
| 4222 if_indexisnotzero(assembler, Label::kDeferred); |
| 4223 assembler->Branch(assembler->Float64Equal( |
| 4224 index_value, assembler->Float64Constant(0.0)), |
| 4225 &if_indexiszero, &if_indexisnotzero); |
| 4226 |
| 4227 assembler->Bind(&if_indexiszero); |
| 4228 { |
| 4229 var_position.Bind(assembler->SmiConstant(Smi::FromInt(0))); |
| 4230 assembler->Goto(&if_positionissmi); |
| 4231 } |
| 4232 |
| 4233 assembler->Bind(&if_indexisnotzero); |
| 4234 { |
| 4235 // The {index} is some other integral Number, that is definitely |
| 4236 // neither -0.0 nor in Smi range. |
| 4237 assembler->Return(assembler->EmptyStringConstant()); |
| 4238 } |
| 4239 } |
| 4240 } |
| 4241 assembler->Bind(&if_positionissmi); |
| 4242 position = var_position.value(); |
| 4243 |
| 4244 // Determine the actual length of the {receiver} String. |
| 4245 Node* receiver_length = |
| 4246 assembler->LoadObjectField(receiver, String::kLengthOffset); |
| 4247 |
| 4248 // Return "" if the Smi {position} is outside the bounds of the {receiver}. |
| 4249 Label if_positioninbounds(assembler), |
| 4250 if_positionnotinbounds(assembler, Label::kDeferred); |
| 4251 assembler->Branch(assembler->SmiAboveOrEqual(position, receiver_length), |
| 4252 &if_positionnotinbounds, &if_positioninbounds); |
| 4253 assembler->Bind(&if_positionnotinbounds); |
| 4254 assembler->Return(assembler->EmptyStringConstant()); |
| 4255 assembler->Bind(&if_positioninbounds); |
| 4256 } |
| 4257 |
| 4258 // Load the character code at the {position} from the {receiver}. |
| 4259 Node* code = assembler->StringCharCodeAt(receiver, position); |
| 4260 |
| 4261 // And return the single character string with only that {code}. |
| 4262 Node* result = assembler->StringFromCharCode(code); |
| 4263 assembler->Return(result); |
| 4264 } |
| 4265 |
| 4266 // ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos ) |
| 4267 void Builtins::Generate_StringPrototypeCharCodeAt( |
| 4268 compiler::CodeStubAssembler* assembler) { |
| 4269 typedef compiler::CodeStubAssembler::Label Label; |
| 4270 typedef compiler::Node Node; |
| 4271 typedef compiler::CodeStubAssembler::Variable Variable; |
| 4272 |
| 4273 Node* receiver = assembler->Parameter(0); |
| 4274 Node* position = assembler->Parameter(1); |
| 4275 Node* context = assembler->Parameter(4); |
| 4276 |
| 4277 // Check that {receiver} is coercible to Object and convert it to a String. |
| 4278 receiver = |
| 4279 assembler->ToThisString(context, receiver, "String.prototype.charCodeAt"); |
| 4280 |
| 4281 // Convert the {position} to a Smi and check that it's in bounds of the |
| 4282 // {receiver}. |
| 4283 // TODO(bmeurer): Find an abstraction for this! |
| 4284 { |
| 4285 // Check if the {position} is already a Smi. |
| 4286 Variable var_position(assembler, MachineRepresentation::kTagged); |
| 4287 var_position.Bind(position); |
| 4288 Label if_positionissmi(assembler), |
| 4289 if_positionisnotsmi(assembler, Label::kDeferred); |
| 4290 assembler->Branch(assembler->WordIsSmi(position), &if_positionissmi, |
| 4291 &if_positionisnotsmi); |
| 4292 assembler->Bind(&if_positionisnotsmi); |
| 4293 { |
| 4294 // Convert the {position} to an Integer via the ToIntegerStub. |
| 4295 Callable callable = CodeFactory::ToInteger(assembler->isolate()); |
| 4296 Node* index = assembler->CallStub(callable, context, position); |
| 4297 |
| 4298 // Check if the resulting {index} is now a Smi. |
| 4299 Label if_indexissmi(assembler, Label::kDeferred), |
| 4300 if_indexisnotsmi(assembler, Label::kDeferred); |
| 4301 assembler->Branch(assembler->WordIsSmi(index), &if_indexissmi, |
| 4302 &if_indexisnotsmi); |
| 4303 |
| 4304 assembler->Bind(&if_indexissmi); |
| 4305 { |
| 4306 var_position.Bind(index); |
| 4307 assembler->Goto(&if_positionissmi); |
| 4308 } |
| 4309 |
| 4310 assembler->Bind(&if_indexisnotsmi); |
| 4311 { |
| 4312 // The ToIntegerStub canonicalizes everything in Smi range to Smi |
| 4313 // representation, so any HeapNumber returned is not in Smi range. |
| 4314 // The only exception here is -0.0, which we treat as 0. |
| 4315 Node* index_value = assembler->LoadHeapNumberValue(index); |
| 4316 Label if_indexiszero(assembler, Label::kDeferred), |
| 4317 if_indexisnotzero(assembler, Label::kDeferred); |
| 4318 assembler->Branch(assembler->Float64Equal( |
| 4319 index_value, assembler->Float64Constant(0.0)), |
| 4320 &if_indexiszero, &if_indexisnotzero); |
| 4321 |
| 4322 assembler->Bind(&if_indexiszero); |
| 4323 { |
| 4324 var_position.Bind(assembler->SmiConstant(Smi::FromInt(0))); |
| 4325 assembler->Goto(&if_positionissmi); |
| 4326 } |
| 4327 |
| 4328 assembler->Bind(&if_indexisnotzero); |
| 4329 { |
| 4330 // The {index} is some other integral Number, that is definitely |
| 4331 // neither -0.0 nor in Smi range. |
| 4332 assembler->Return(assembler->NaNConstant()); |
| 4333 } |
| 4334 } |
| 4335 } |
| 4336 assembler->Bind(&if_positionissmi); |
| 4337 position = var_position.value(); |
| 4338 |
| 4339 // Determine the actual length of the {receiver} String. |
| 4340 Node* receiver_length = |
| 4341 assembler->LoadObjectField(receiver, String::kLengthOffset); |
| 4342 |
| 4343 // Return NaN if the Smi {position} is outside the bounds of the {receiver}. |
| 4344 Label if_positioninbounds(assembler), |
| 4345 if_positionnotinbounds(assembler, Label::kDeferred); |
| 4346 assembler->Branch(assembler->SmiAboveOrEqual(position, receiver_length), |
| 4347 &if_positionnotinbounds, &if_positioninbounds); |
| 4348 assembler->Bind(&if_positionnotinbounds); |
| 4349 assembler->Return(assembler->NaNConstant()); |
| 4350 assembler->Bind(&if_positioninbounds); |
| 4351 } |
| 4352 |
| 4353 // Load the character at the {position} from the {receiver}. |
| 4354 Node* value = assembler->StringCharCodeAt(receiver, position); |
| 4355 Node* result = assembler->SmiFromWord32(value); |
| 4356 assembler->Return(result); |
| 4357 } |
| 4358 |
| 4359 // ----------------------------------------------------------------------------- |
| 4360 // ES6 section 21.1 ArrayBuffer Objects |
4168 | 4361 |
4169 // ES6 section 24.1.2.1 ArrayBuffer ( length ) for the [[Call]] case. | 4362 // ES6 section 24.1.2.1 ArrayBuffer ( length ) for the [[Call]] case. |
4170 BUILTIN(ArrayBufferConstructor) { | 4363 BUILTIN(ArrayBufferConstructor) { |
4171 HandleScope scope(isolate); | 4364 HandleScope scope(isolate); |
4172 Handle<JSFunction> target = args.target<JSFunction>(); | 4365 Handle<JSFunction> target = args.target<JSFunction>(); |
4173 DCHECK(*target == target->native_context()->array_buffer_fun() || | 4366 DCHECK(*target == target->native_context()->array_buffer_fun() || |
4174 *target == target->native_context()->shared_array_buffer_fun()); | 4367 *target == target->native_context()->shared_array_buffer_fun()); |
4175 THROW_NEW_ERROR_RETURN_FAILURE( | 4368 THROW_NEW_ERROR_RETURN_FAILURE( |
4176 isolate, NewTypeError(MessageTemplate::kConstructorNotFunction, | 4369 isolate, NewTypeError(MessageTemplate::kConstructorNotFunction, |
4177 handle(target->shared()->name(), isolate))); | 4370 handle(target->shared()->name(), isolate))); |
(...skipping 773 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4951 BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T) | 5144 BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T) |
4952 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) | 5145 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) |
4953 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 5146 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) |
4954 #undef DEFINE_BUILTIN_ACCESSOR_C | 5147 #undef DEFINE_BUILTIN_ACCESSOR_C |
4955 #undef DEFINE_BUILTIN_ACCESSOR_A | 5148 #undef DEFINE_BUILTIN_ACCESSOR_A |
4956 #undef DEFINE_BUILTIN_ACCESSOR_T | 5149 #undef DEFINE_BUILTIN_ACCESSOR_T |
4957 #undef DEFINE_BUILTIN_ACCESSOR_H | 5150 #undef DEFINE_BUILTIN_ACCESSOR_H |
4958 | 5151 |
4959 } // namespace internal | 5152 } // namespace internal |
4960 } // namespace v8 | 5153 } // namespace v8 |
OLD | NEW |