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

Side by Side Diff: src/code-stubs.cc

Issue 2363333003: [turbofan] Lower StringEqual and friends in EffectControlLinearizer. (Closed)
Patch Set: Created 4 years, 2 months 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
OLDNEW
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/code-stubs.h" 5 #include "src/code-stubs.h"
6 6
7 #include <sstream> 7 #include <sstream>
8 8
9 #include "src/ast/ast.h" 9 #include "src/ast/ast.h"
10 #include "src/bootstrapper.h" 10 #include "src/bootstrapper.h"
(...skipping 4148 matching lines...) Expand 10 before | Expand all | Expand 10 after
4159 assembler->Bind(&if_notequal); 4159 assembler->Bind(&if_notequal);
4160 { 4160 {
4161 result.Bind(assembler->BooleanConstant(mode == kNegateResult)); 4161 result.Bind(assembler->BooleanConstant(mode == kNegateResult));
4162 assembler->Goto(&end); 4162 assembler->Goto(&end);
4163 } 4163 }
4164 4164
4165 assembler->Bind(&end); 4165 assembler->Bind(&end);
4166 return result.value(); 4166 return result.value();
4167 } 4167 }
4168 4168
4169 void GenerateStringRelationalComparison(CodeStubAssembler* assembler,
4170 RelationalComparisonMode mode) {
4171 typedef CodeStubAssembler::Label Label;
4172 typedef compiler::Node Node;
4173 typedef CodeStubAssembler::Variable Variable;
4174
4175 Node* lhs = assembler->Parameter(0);
4176 Node* rhs = assembler->Parameter(1);
4177 Node* context = assembler->Parameter(2);
4178
4179 Label if_less(assembler), if_equal(assembler), if_greater(assembler);
4180
4181 // Fast check to see if {lhs} and {rhs} refer to the same String object.
4182 Label if_same(assembler), if_notsame(assembler);
4183 assembler->Branch(assembler->WordEqual(lhs, rhs), &if_same, &if_notsame);
4184
4185 assembler->Bind(&if_same);
4186 assembler->Goto(&if_equal);
4187
4188 assembler->Bind(&if_notsame);
4189 {
4190 // Load instance types of {lhs} and {rhs}.
4191 Node* lhs_instance_type = assembler->LoadInstanceType(lhs);
4192 Node* rhs_instance_type = assembler->LoadInstanceType(rhs);
4193
4194 // Combine the instance types into a single 16-bit value, so we can check
4195 // both of them at once.
4196 Node* both_instance_types = assembler->Word32Or(
4197 lhs_instance_type,
4198 assembler->Word32Shl(rhs_instance_type, assembler->Int32Constant(8)));
4199
4200 // Check that both {lhs} and {rhs} are flat one-byte strings.
4201 int const kBothSeqOneByteStringMask =
4202 kStringEncodingMask | kStringRepresentationMask |
4203 ((kStringEncodingMask | kStringRepresentationMask) << 8);
4204 int const kBothSeqOneByteStringTag =
4205 kOneByteStringTag | kSeqStringTag |
4206 ((kOneByteStringTag | kSeqStringTag) << 8);
4207 Label if_bothonebyteseqstrings(assembler),
4208 if_notbothonebyteseqstrings(assembler);
4209 assembler->Branch(assembler->Word32Equal(
4210 assembler->Word32And(both_instance_types,
4211 assembler->Int32Constant(
4212 kBothSeqOneByteStringMask)),
4213 assembler->Int32Constant(kBothSeqOneByteStringTag)),
4214 &if_bothonebyteseqstrings, &if_notbothonebyteseqstrings);
4215
4216 assembler->Bind(&if_bothonebyteseqstrings);
4217 {
4218 // Load the length of {lhs} and {rhs}.
4219 Node* lhs_length = assembler->LoadStringLength(lhs);
4220 Node* rhs_length = assembler->LoadStringLength(rhs);
4221
4222 // Determine the minimum length.
4223 Node* length = assembler->SmiMin(lhs_length, rhs_length);
4224
4225 // Compute the effective offset of the first character.
4226 Node* begin = assembler->IntPtrConstant(SeqOneByteString::kHeaderSize -
4227 kHeapObjectTag);
4228
4229 // Compute the first offset after the string from the length.
4230 Node* end = assembler->IntPtrAdd(begin, assembler->SmiUntag(length));
4231
4232 // Loop over the {lhs} and {rhs} strings to see if they are equal.
4233 Variable var_offset(assembler, MachineType::PointerRepresentation());
4234 Label loop(assembler, &var_offset);
4235 var_offset.Bind(begin);
4236 assembler->Goto(&loop);
4237 assembler->Bind(&loop);
4238 {
4239 // Check if {offset} equals {end}.
4240 Node* offset = var_offset.value();
4241 Label if_done(assembler), if_notdone(assembler);
4242 assembler->Branch(assembler->WordEqual(offset, end), &if_done,
4243 &if_notdone);
4244
4245 assembler->Bind(&if_notdone);
4246 {
4247 // Load the next characters from {lhs} and {rhs}.
4248 Node* lhs_value = assembler->Load(MachineType::Uint8(), lhs, offset);
4249 Node* rhs_value = assembler->Load(MachineType::Uint8(), rhs, offset);
4250
4251 // Check if the characters match.
4252 Label if_valueissame(assembler), if_valueisnotsame(assembler);
4253 assembler->Branch(assembler->Word32Equal(lhs_value, rhs_value),
4254 &if_valueissame, &if_valueisnotsame);
4255
4256 assembler->Bind(&if_valueissame);
4257 {
4258 // Advance to next character.
4259 var_offset.Bind(
4260 assembler->IntPtrAdd(offset, assembler->IntPtrConstant(1)));
4261 }
4262 assembler->Goto(&loop);
4263
4264 assembler->Bind(&if_valueisnotsame);
4265 assembler->BranchIf(assembler->Uint32LessThan(lhs_value, rhs_value),
4266 &if_less, &if_greater);
4267 }
4268
4269 assembler->Bind(&if_done);
4270 {
4271 // All characters up to the min length are equal, decide based on
4272 // string length.
4273 Label if_lengthisequal(assembler), if_lengthisnotequal(assembler);
4274 assembler->Branch(assembler->SmiEqual(lhs_length, rhs_length),
4275 &if_lengthisequal, &if_lengthisnotequal);
4276
4277 assembler->Bind(&if_lengthisequal);
4278 assembler->Goto(&if_equal);
4279
4280 assembler->Bind(&if_lengthisnotequal);
4281 assembler->BranchIfSmiLessThan(lhs_length, rhs_length, &if_less,
4282 &if_greater);
4283 }
4284 }
4285 }
4286
4287 assembler->Bind(&if_notbothonebyteseqstrings);
4288 {
4289 // TODO(bmeurer): Add fast case support for flattened cons strings;
4290 // also add support for two byte string relational comparisons.
4291 switch (mode) {
4292 case kLessThan:
4293 assembler->TailCallRuntime(Runtime::kStringLessThan, context, lhs,
4294 rhs);
4295 break;
4296 case kLessThanOrEqual:
4297 assembler->TailCallRuntime(Runtime::kStringLessThanOrEqual, context,
4298 lhs, rhs);
4299 break;
4300 case kGreaterThan:
4301 assembler->TailCallRuntime(Runtime::kStringGreaterThan, context, lhs,
4302 rhs);
4303 break;
4304 case kGreaterThanOrEqual:
4305 assembler->TailCallRuntime(Runtime::kStringGreaterThanOrEqual,
4306 context, lhs, rhs);
4307 break;
4308 }
4309 }
4310 }
4311
4312 assembler->Bind(&if_less);
4313 switch (mode) {
4314 case kLessThan:
4315 case kLessThanOrEqual:
4316 assembler->Return(assembler->BooleanConstant(true));
4317 break;
4318
4319 case kGreaterThan:
4320 case kGreaterThanOrEqual:
4321 assembler->Return(assembler->BooleanConstant(false));
4322 break;
4323 }
4324
4325 assembler->Bind(&if_equal);
4326 switch (mode) {
4327 case kLessThan:
4328 case kGreaterThan:
4329 assembler->Return(assembler->BooleanConstant(false));
4330 break;
4331
4332 case kLessThanOrEqual:
4333 case kGreaterThanOrEqual:
4334 assembler->Return(assembler->BooleanConstant(true));
4335 break;
4336 }
4337
4338 assembler->Bind(&if_greater);
4339 switch (mode) {
4340 case kLessThan:
4341 case kLessThanOrEqual:
4342 assembler->Return(assembler->BooleanConstant(false));
4343 break;
4344
4345 case kGreaterThan:
4346 case kGreaterThanOrEqual:
4347 assembler->Return(assembler->BooleanConstant(true));
4348 break;
4349 }
4350 }
4351
4352 void GenerateStringEqual(CodeStubAssembler* assembler, ResultMode mode) {
4353 // Here's pseudo-code for the algorithm below in case of kDontNegateResult
4354 // mode; for kNegateResult mode we properly negate the result.
4355 //
4356 // if (lhs == rhs) return true;
4357 // if (lhs->length() != rhs->length()) return false;
4358 // if (lhs->IsInternalizedString() && rhs->IsInternalizedString()) {
4359 // return false;
4360 // }
4361 // if (lhs->IsSeqOneByteString() && rhs->IsSeqOneByteString()) {
4362 // for (i = 0; i != lhs->length(); ++i) {
4363 // if (lhs[i] != rhs[i]) return false;
4364 // }
4365 // return true;
4366 // }
4367 // return %StringEqual(lhs, rhs);
4368
4369 typedef CodeStubAssembler::Label Label;
4370 typedef compiler::Node Node;
4371 typedef CodeStubAssembler::Variable Variable;
4372
4373 Node* lhs = assembler->Parameter(0);
4374 Node* rhs = assembler->Parameter(1);
4375 Node* context = assembler->Parameter(2);
4376
4377 Label if_equal(assembler), if_notequal(assembler);
4378
4379 // Fast check to see if {lhs} and {rhs} refer to the same String object.
4380 Label if_same(assembler), if_notsame(assembler);
4381 assembler->Branch(assembler->WordEqual(lhs, rhs), &if_same, &if_notsame);
4382
4383 assembler->Bind(&if_same);
4384 assembler->Goto(&if_equal);
4385
4386 assembler->Bind(&if_notsame);
4387 {
4388 // The {lhs} and {rhs} don't refer to the exact same String object.
4389
4390 // Load the length of {lhs} and {rhs}.
4391 Node* lhs_length = assembler->LoadStringLength(lhs);
4392 Node* rhs_length = assembler->LoadStringLength(rhs);
4393
4394 // Check if the lengths of {lhs} and {rhs} are equal.
4395 Label if_lengthisequal(assembler), if_lengthisnotequal(assembler);
4396 assembler->Branch(assembler->WordEqual(lhs_length, rhs_length),
4397 &if_lengthisequal, &if_lengthisnotequal);
4398
4399 assembler->Bind(&if_lengthisequal);
4400 {
4401 // Load instance types of {lhs} and {rhs}.
4402 Node* lhs_instance_type = assembler->LoadInstanceType(lhs);
4403 Node* rhs_instance_type = assembler->LoadInstanceType(rhs);
4404
4405 // Combine the instance types into a single 16-bit value, so we can check
4406 // both of them at once.
4407 Node* both_instance_types = assembler->Word32Or(
4408 lhs_instance_type,
4409 assembler->Word32Shl(rhs_instance_type, assembler->Int32Constant(8)));
4410
4411 // Check if both {lhs} and {rhs} are internalized.
4412 int const kBothInternalizedMask =
4413 kIsNotInternalizedMask | (kIsNotInternalizedMask << 8);
4414 int const kBothInternalizedTag =
4415 kInternalizedTag | (kInternalizedTag << 8);
4416 Label if_bothinternalized(assembler), if_notbothinternalized(assembler);
4417 assembler->Branch(assembler->Word32Equal(
4418 assembler->Word32And(both_instance_types,
4419 assembler->Int32Constant(
4420 kBothInternalizedMask)),
4421 assembler->Int32Constant(kBothInternalizedTag)),
4422 &if_bothinternalized, &if_notbothinternalized);
4423
4424 assembler->Bind(&if_bothinternalized);
4425 {
4426 // Fast negative check for internalized-to-internalized equality.
4427 assembler->Goto(&if_notequal);
4428 }
4429
4430 assembler->Bind(&if_notbothinternalized);
4431 {
4432 // Check that both {lhs} and {rhs} are flat one-byte strings.
4433 int const kBothSeqOneByteStringMask =
4434 kStringEncodingMask | kStringRepresentationMask |
4435 ((kStringEncodingMask | kStringRepresentationMask) << 8);
4436 int const kBothSeqOneByteStringTag =
4437 kOneByteStringTag | kSeqStringTag |
4438 ((kOneByteStringTag | kSeqStringTag) << 8);
4439 Label if_bothonebyteseqstrings(assembler),
4440 if_notbothonebyteseqstrings(assembler);
4441 assembler->Branch(
4442 assembler->Word32Equal(
4443 assembler->Word32And(
4444 both_instance_types,
4445 assembler->Int32Constant(kBothSeqOneByteStringMask)),
4446 assembler->Int32Constant(kBothSeqOneByteStringTag)),
4447 &if_bothonebyteseqstrings, &if_notbothonebyteseqstrings);
4448
4449 assembler->Bind(&if_bothonebyteseqstrings);
4450 {
4451 // Compute the effective offset of the first character.
4452 Node* begin = assembler->IntPtrConstant(
4453 SeqOneByteString::kHeaderSize - kHeapObjectTag);
4454
4455 // Compute the first offset after the string from the length.
4456 Node* end =
4457 assembler->IntPtrAdd(begin, assembler->SmiUntag(lhs_length));
4458
4459 // Loop over the {lhs} and {rhs} strings to see if they are equal.
4460 Variable var_offset(assembler, MachineType::PointerRepresentation());
4461 Label loop(assembler, &var_offset);
4462 var_offset.Bind(begin);
4463 assembler->Goto(&loop);
4464 assembler->Bind(&loop);
4465 {
4466 // Check if {offset} equals {end}.
4467 Node* offset = var_offset.value();
4468 Label if_done(assembler), if_notdone(assembler);
4469 assembler->Branch(assembler->WordEqual(offset, end), &if_done,
4470 &if_notdone);
4471
4472 assembler->Bind(&if_notdone);
4473 {
4474 // Load the next characters from {lhs} and {rhs}.
4475 Node* lhs_value =
4476 assembler->Load(MachineType::Uint8(), lhs, offset);
4477 Node* rhs_value =
4478 assembler->Load(MachineType::Uint8(), rhs, offset);
4479
4480 // Check if the characters match.
4481 Label if_valueissame(assembler), if_valueisnotsame(assembler);
4482 assembler->Branch(assembler->Word32Equal(lhs_value, rhs_value),
4483 &if_valueissame, &if_valueisnotsame);
4484
4485 assembler->Bind(&if_valueissame);
4486 {
4487 // Advance to next character.
4488 var_offset.Bind(
4489 assembler->IntPtrAdd(offset, assembler->IntPtrConstant(1)));
4490 }
4491 assembler->Goto(&loop);
4492
4493 assembler->Bind(&if_valueisnotsame);
4494 assembler->Goto(&if_notequal);
4495 }
4496
4497 assembler->Bind(&if_done);
4498 assembler->Goto(&if_equal);
4499 }
4500 }
4501
4502 assembler->Bind(&if_notbothonebyteseqstrings);
4503 {
4504 // TODO(bmeurer): Add fast case support for flattened cons strings;
4505 // also add support for two byte string equality checks.
4506 Runtime::FunctionId function_id = (mode == kDontNegateResult)
4507 ? Runtime::kStringEqual
4508 : Runtime::kStringNotEqual;
4509 assembler->TailCallRuntime(function_id, context, lhs, rhs);
4510 }
4511 }
4512 }
4513
4514 assembler->Bind(&if_lengthisnotequal);
4515 {
4516 // Mismatch in length of {lhs} and {rhs}, cannot be equal.
4517 assembler->Goto(&if_notequal);
4518 }
4519 }
4520
4521 assembler->Bind(&if_equal);
4522 assembler->Return(assembler->BooleanConstant(mode == kDontNegateResult));
4523
4524 assembler->Bind(&if_notequal);
4525 assembler->Return(assembler->BooleanConstant(mode == kNegateResult));
4526 }
4527
4528 } // namespace 4169 } // namespace
4529 4170
4530 void LoadApiGetterStub::GenerateAssembly(CodeStubAssembler* assembler) const { 4171 void LoadApiGetterStub::GenerateAssembly(CodeStubAssembler* assembler) const {
4531 typedef compiler::Node Node; 4172 typedef compiler::Node Node;
4532 Node* context = assembler->Parameter(Descriptor::kContext); 4173 Node* context = assembler->Parameter(Descriptor::kContext);
4533 Node* receiver = assembler->Parameter(Descriptor::kReceiver); 4174 Node* receiver = assembler->Parameter(Descriptor::kReceiver);
4534 // For now we only support receiver_is_holder. 4175 // For now we only support receiver_is_holder.
4535 DCHECK(receiver_is_holder()); 4176 DCHECK(receiver_is_holder());
4536 Node* holder = receiver; 4177 Node* holder = receiver;
4537 Node* map = assembler->LoadMap(receiver); 4178 Node* map = assembler->LoadMap(receiver);
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
4816 } 4457 }
4817 4458
4818 // static 4459 // static
4819 compiler::Node* StrictNotEqualStub::Generate(CodeStubAssembler* assembler, 4460 compiler::Node* StrictNotEqualStub::Generate(CodeStubAssembler* assembler,
4820 compiler::Node* lhs, 4461 compiler::Node* lhs,
4821 compiler::Node* rhs, 4462 compiler::Node* rhs,
4822 compiler::Node* context) { 4463 compiler::Node* context) {
4823 return GenerateStrictEqual(assembler, kNegateResult, lhs, rhs, context); 4464 return GenerateStrictEqual(assembler, kNegateResult, lhs, rhs, context);
4824 } 4465 }
4825 4466
4826 void StringEqualStub::GenerateAssembly(CodeStubAssembler* assembler) const {
4827 GenerateStringEqual(assembler, kDontNegateResult);
4828 }
4829
4830 void StringNotEqualStub::GenerateAssembly(CodeStubAssembler* assembler) const {
4831 GenerateStringEqual(assembler, kNegateResult);
4832 }
4833
4834 void StringLessThanStub::GenerateAssembly(CodeStubAssembler* assembler) const {
4835 GenerateStringRelationalComparison(assembler, kLessThan);
4836 }
4837
4838 void StringLessThanOrEqualStub::GenerateAssembly(
4839 CodeStubAssembler* assembler) const {
4840 GenerateStringRelationalComparison(assembler, kLessThanOrEqual);
4841 }
4842
4843 void StringGreaterThanStub::GenerateAssembly(
4844 CodeStubAssembler* assembler) const {
4845 GenerateStringRelationalComparison(assembler, kGreaterThan);
4846 }
4847
4848 void StringGreaterThanOrEqualStub::GenerateAssembly(
4849 CodeStubAssembler* assembler) const {
4850 GenerateStringRelationalComparison(assembler, kGreaterThanOrEqual);
4851 }
4852
4853 void ToLengthStub::GenerateAssembly(CodeStubAssembler* assembler) const { 4467 void ToLengthStub::GenerateAssembly(CodeStubAssembler* assembler) const {
4854 typedef CodeStubAssembler::Label Label; 4468 typedef CodeStubAssembler::Label Label;
4855 typedef compiler::Node Node; 4469 typedef compiler::Node Node;
4856 typedef CodeStubAssembler::Variable Variable; 4470 typedef CodeStubAssembler::Variable Variable;
4857 4471
4858 Node* context = assembler->Parameter(1); 4472 Node* context = assembler->Parameter(1);
4859 4473
4860 // We might need to loop once for ToNumber conversion. 4474 // We might need to loop once for ToNumber conversion.
4861 Variable var_len(assembler, MachineRepresentation::kTagged); 4475 Variable var_len(assembler, MachineRepresentation::kTagged);
4862 Label loop(assembler, &var_len); 4476 Label loop(assembler, &var_len);
(...skipping 1398 matching lines...) Expand 10 before | Expand all | Expand 10 after
6261 5875
6262 if (type == MachineType::Pointer()) { 5876 if (type == MachineType::Pointer()) {
6263 return Representation::External(); 5877 return Representation::External();
6264 } 5878 }
6265 5879
6266 return Representation::Tagged(); 5880 return Representation::Tagged();
6267 } 5881 }
6268 5882
6269 } // namespace internal 5883 } // namespace internal
6270 } // namespace v8 5884 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698