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

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

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

Powered by Google App Engine
This is Rietveld 408576698