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

Side by Side Diff: src/hydrogen.cc

Issue 6243008: Support StringCharCodeAt in hydrogen/lithium. (Closed)
Patch Set: Addressed Florian's comments. Created 9 years, 11 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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 16 matching lines...) Expand all
27 27
28 #include "hydrogen.h" 28 #include "hydrogen.h"
29 29
30 #include "codegen.h" 30 #include "codegen.h"
31 #include "data-flow.h" 31 #include "data-flow.h"
32 #include "full-codegen.h" 32 #include "full-codegen.h"
33 #include "hashmap.h" 33 #include "hashmap.h"
34 #include "lithium-allocator.h" 34 #include "lithium-allocator.h"
35 #include "parser.h" 35 #include "parser.h"
36 #include "scopes.h" 36 #include "scopes.h"
37 #include "stub-cache.h"
37 38
38 #if V8_TARGET_ARCH_IA32 39 #if V8_TARGET_ARCH_IA32
39 #include "ia32/lithium-codegen-ia32.h" 40 #include "ia32/lithium-codegen-ia32.h"
40 #elif V8_TARGET_ARCH_X64 41 #elif V8_TARGET_ARCH_X64
41 #include "x64/lithium-codegen-x64.h" 42 #include "x64/lithium-codegen-x64.h"
42 #elif V8_TARGET_ARCH_ARM 43 #elif V8_TARGET_ARCH_ARM
43 #include "arm/lithium-codegen-arm.h" 44 #include "arm/lithium-codegen-arm.h"
44 #else 45 #else
45 #error Unsupported target architecture. 46 #error Unsupported target architecture.
46 #endif 47 #endif
(...skipping 4092 matching lines...) Expand 10 before | Expand all | Expand 10 after
4139 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) { 4140 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) {
4140 ASSERT(target->IsInlineReturnTarget()); 4141 ASSERT(target->IsInlineReturnTarget());
4141 AddInstruction(new HLeaveInlined); 4142 AddInstruction(new HLeaveInlined);
4142 HEnvironment* outer = last_environment()->outer(); 4143 HEnvironment* outer = last_environment()->outer();
4143 if (return_value != NULL) outer->Push(return_value); 4144 if (return_value != NULL) outer->Push(return_value);
4144 UpdateEnvironment(outer); 4145 UpdateEnvironment(outer);
4145 Goto(target); 4146 Goto(target);
4146 } 4147 }
4147 4148
4148 4149
4149 bool HGraphBuilder::TryMathFunctionInline(Call* expr) { 4150 bool HGraphBuilder::TryInlineBuiltinFunction(Call* expr,
4151 HValue* receiver,
4152 Handle<Map> receiver_map,
4153 CheckType check_type) {
4154 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null());
4150 // Try to inline calls like Math.* as operations in the calling function. 4155 // Try to inline calls like Math.* as operations in the calling function.
4151 if (!expr->target()->shared()->IsBuiltinMathFunction()) return false; 4156 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
fschneider 2011/01/19 16:23:44 Maybe we don't need IsBuiltinMathFunction() anymor
Vitaly Repeshko 2011/01/19 20:08:41 Done.
4152 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); 4157 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
4153 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 4158 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
4154 switch (id) { 4159 switch (id) {
4160 case kStringCharCodeAt:
4161 if (argument_count == 2 && check_type == STRING_CHECK) {
4162 HValue* index = Pop();
4163 HValue* string = Pop();
4164 ASSERT(!expr->holder().is_null());
4165 AddInstruction(new HCheckPrototypeMaps(
4166 oracle()->GetPrototypeForPrimitiveCheck(STRING_CHECK),
4167 expr->holder()));
4168 HStringCharCodeAt* result = BuildStringCharCodeAt(string, index);
4169 ast_context()->ReturnInstruction(result, expr->id());
4170 return true;
4171 }
4172 break;
4155 case kMathRound: 4173 case kMathRound:
4156 case kMathFloor: 4174 case kMathFloor:
4157 case kMathAbs: 4175 case kMathAbs:
4158 case kMathSqrt: 4176 case kMathSqrt:
4159 case kMathLog: 4177 case kMathLog:
4160 case kMathSin: 4178 case kMathSin:
4161 case kMathCos: 4179 case kMathCos:
4162 if (argument_count == 2) { 4180 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) {
4181 AddCheckConstantFunction(expr, receiver, receiver_map, true);
4163 HValue* argument = Pop(); 4182 HValue* argument = Pop();
4164 Drop(1); // Receiver. 4183 Drop(1); // Receiver.
4165 HUnaryMathOperation* op = new HUnaryMathOperation(argument, id); 4184 HUnaryMathOperation* op = new HUnaryMathOperation(argument, id);
4166 op->set_position(expr->position()); 4185 op->set_position(expr->position());
4167 ast_context()->ReturnInstruction(op, expr->id()); 4186 ast_context()->ReturnInstruction(op, expr->id());
4168 return true; 4187 return true;
4169 } 4188 }
4170 break; 4189 break;
4171 case kMathPow: 4190 case kMathPow:
4172 if (argument_count == 3) { 4191 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) {
4192 AddCheckConstantFunction(expr, receiver, receiver_map, true);
4173 HValue* right = Pop(); 4193 HValue* right = Pop();
4174 HValue* left = Pop(); 4194 HValue* left = Pop();
4175 Pop(); // Pop receiver. 4195 Pop(); // Pop receiver.
4176 HInstruction* result = NULL; 4196 HInstruction* result = NULL;
4177 // Use sqrt() if exponent is 0.5 or -0.5. 4197 // Use sqrt() if exponent is 0.5 or -0.5.
4178 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { 4198 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
4179 double exponent = HConstant::cast(right)->DoubleValue(); 4199 double exponent = HConstant::cast(right)->DoubleValue();
4180 if (exponent == 0.5) { 4200 if (exponent == 0.5) {
4181 result = new HUnaryMathOperation(left, kMathPowHalf); 4201 result = new HUnaryMathOperation(left, kMathPowHalf);
4182 ast_context()->ReturnInstruction(result, expr->id());
4183 return true;
4184 } else if (exponent == -0.5) { 4202 } else if (exponent == -0.5) {
4185 HConstant* double_one = 4203 HConstant* double_one =
4186 new HConstant(Handle<Object>(Smi::FromInt(1)), 4204 new HConstant(Handle<Object>(Smi::FromInt(1)),
4187 Representation::Double()); 4205 Representation::Double());
4188 AddInstruction(double_one); 4206 AddInstruction(double_one);
4189 HUnaryMathOperation* square_root = 4207 HUnaryMathOperation* square_root =
4190 new HUnaryMathOperation(left, kMathPowHalf); 4208 new HUnaryMathOperation(left, kMathPowHalf);
4191 AddInstruction(square_root); 4209 AddInstruction(square_root);
4192 // MathPowHalf doesn't have side effects so there's no need for 4210 // MathPowHalf doesn't have side effects so there's no need for
4193 // an environment simulation here. 4211 // an environment simulation here.
4194 ASSERT(!square_root->HasSideEffects()); 4212 ASSERT(!square_root->HasSideEffects());
4195 result = new HDiv(double_one, square_root); 4213 result = new HDiv(double_one, square_root);
4196 ast_context()->ReturnInstruction(result, expr->id());
4197 return true;
4198 } else if (exponent == 2.0) { 4214 } else if (exponent == 2.0) {
4199 result = new HMul(left, left); 4215 result = new HMul(left, left);
4200 ast_context()->ReturnInstruction(result, expr->id());
4201 return true;
4202 } 4216 }
4203 } else if (right->IsConstant() && 4217 } else if (right->IsConstant() &&
4204 HConstant::cast(right)->HasInteger32Value() && 4218 HConstant::cast(right)->HasInteger32Value() &&
4205 HConstant::cast(right)->Integer32Value() == 2) { 4219 HConstant::cast(right)->Integer32Value() == 2) {
4206 result = new HMul(left, left); 4220 result = new HMul(left, left);
4207 ast_context()->ReturnInstruction(result, expr->id());
4208 return true;
4209 } 4221 }
4210 4222
4211 result = new HPower(left, right); 4223 if (result == NULL) {
4224 result = new HPower(left, right);
4225 }
4212 ast_context()->ReturnInstruction(result, expr->id()); 4226 ast_context()->ReturnInstruction(result, expr->id());
4213 return true; 4227 return true;
4214 } 4228 }
4215 break; 4229 break;
4216 default: 4230 default:
4217 // Not yet supported for inlining. 4231 // Not yet supported for inlining.
4218 break; 4232 break;
4219 } 4233 }
4220 return false; 4234 return false;
4221 } 4235 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
4256 expr->GetReceiverTypes()->first(), 4270 expr->GetReceiverTypes()->first(),
4257 true); 4271 true);
4258 HInstruction* result = 4272 HInstruction* result =
4259 new HApplyArguments(function, receiver, length, elements); 4273 new HApplyArguments(function, receiver, length, elements);
4260 result->set_position(expr->position()); 4274 result->set_position(expr->position());
4261 ast_context()->ReturnInstruction(result, expr->id()); 4275 ast_context()->ReturnInstruction(result, expr->id());
4262 return true; 4276 return true;
4263 } 4277 }
4264 4278
4265 4279
4280 static bool HasCustomCallGenerator(Handle<JSFunction> function) {
4281 SharedFunctionInfo* info = function->shared();
4282 return info->HasBuiltinFunctionId() &&
4283 CallStubCompiler::HasCustomCallGenerator(info->builtin_function_id());
4284 }
4285
4286
4266 void HGraphBuilder::VisitCall(Call* expr) { 4287 void HGraphBuilder::VisitCall(Call* expr) {
4267 Expression* callee = expr->expression(); 4288 Expression* callee = expr->expression();
4268 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 4289 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
4269 HCall* call = NULL; 4290 HCall* call = NULL;
4270 4291
4271 Property* prop = callee->AsProperty(); 4292 Property* prop = callee->AsProperty();
4272 if (prop != NULL) { 4293 if (prop != NULL) {
4273 if (!prop->key()->IsPropertyName()) { 4294 if (!prop->key()->IsPropertyName()) {
4274 // Keyed function call. 4295 // Keyed function call.
4275 VisitArgument(prop->obj()); 4296 VisitArgument(prop->obj());
(...skipping 26 matching lines...) Expand all
4302 HValue* receiver = VisitArgument(prop->obj()); 4323 HValue* receiver = VisitArgument(prop->obj());
4303 CHECK_BAILOUT; 4324 CHECK_BAILOUT;
4304 VisitArgumentList(expr->arguments()); 4325 VisitArgumentList(expr->arguments());
4305 CHECK_BAILOUT; 4326 CHECK_BAILOUT;
4306 4327
4307 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 4328 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4308 4329
4309 expr->RecordTypeFeedback(oracle()); 4330 expr->RecordTypeFeedback(oracle());
4310 ZoneMapList* types = expr->GetReceiverTypes(); 4331 ZoneMapList* types = expr->GetReceiverTypes();
4311 4332
4312 if (expr->IsMonomorphic() && expr->check_type() == RECEIVER_MAP_CHECK) { 4333 if (expr->IsMonomorphic()) {
4313 AddCheckConstantFunction(expr, receiver, types->first(), true); 4334 Handle<Map> receiver_map =
4314 4335 (types == NULL) ? Handle<Map>::null() : types->first();
4315 if (TryMathFunctionInline(expr)) { 4336 if (TryInlineBuiltinFunction(expr,
4337 receiver,
4338 receiver_map,
4339 expr->check_type())) {
4316 return; 4340 return;
4317 } else if (TryInline(expr)) {
4318 if (subgraph()->HasExit()) {
4319 HValue* return_value = Pop();
4320 // If we inlined a function in a test context then we need to emit
4321 // a simulate here to shadow the ones at the end of the
4322 // predecessor blocks. Those environments contain the return
4323 // value on top and do not correspond to any actual state of the
4324 // unoptimized code.
4325 if (ast_context()->IsEffect()) AddSimulate(expr->id());
4326 ast_context()->ReturnValue(return_value);
4327 }
4328 return;
4329 } else {
4330 // Check for bailout, as the TryInline call in the if condition above
4331 // might return false due to bailout during hydrogen processing.
4332 CHECK_BAILOUT;
4333 call = new HCallConstantFunction(expr->target(), argument_count);
4334 } 4341 }
4335 4342
4343 if (HasCustomCallGenerator(expr->target()) ||
4344 expr->check_type() != RECEIVER_MAP_CHECK) {
4345 // When the target has a custom call IC generator, use the IC,
4346 // because it is likely to generate better code. Also use the
4347 // IC when a primitive receiver check is required.
4348 call = new HCallNamed(name, argument_count);
4349 } else {
4350 AddCheckConstantFunction(expr, receiver, receiver_map, true);
4351
4352 if (TryInline(expr)) {
4353 if (subgraph()->HasExit()) {
4354 HValue* return_value = Pop();
4355 // If we inlined a function in a test context then we need to emit
4356 // a simulate here to shadow the ones at the end of the
4357 // predecessor blocks. Those environments contain the return
4358 // value on top and do not correspond to any actual state of the
4359 // unoptimized code.
4360 if (ast_context()->IsEffect()) AddSimulate(expr->id());
4361 ast_context()->ReturnValue(return_value);
4362 }
4363 return;
4364 } else {
4365 // Check for bailout, as the TryInline call in the if condition above
4366 // might return false due to bailout during hydrogen processing.
4367 CHECK_BAILOUT;
4368 call = new HCallConstantFunction(expr->target(), argument_count);
4369 }
4370 }
4336 } else if (types != NULL && types->length() > 1) { 4371 } else if (types != NULL && types->length() > 1) {
4337 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); 4372 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK);
4338 HandlePolymorphicCallNamed(expr, receiver, types, name); 4373 HandlePolymorphicCallNamed(expr, receiver, types, name);
4339 return; 4374 return;
4340 4375
4341 } else { 4376 } else {
4342 call = new HCallNamed(name, argument_count); 4377 call = new HCallNamed(name, argument_count);
4343 } 4378 }
4344 4379
4345 } else { 4380 } else {
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after
4713 4748
4714 ast_context()->ReturnValue(expr->is_postfix() ? before : after); 4749 ast_context()->ReturnValue(expr->is_postfix() ? before : after);
4715 } 4750 }
4716 4751
4717 } else { 4752 } else {
4718 BAILOUT("invalid lhs in count operation"); 4753 BAILOUT("invalid lhs in count operation");
4719 } 4754 }
4720 } 4755 }
4721 4756
4722 4757
4758 HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* string,
4759 HValue* index) {
4760 AddInstruction(new HCheckNonSmi(string));
4761 AddInstruction(new HCheckInstanceType(
4762 string, FIRST_STRING_TYPE, LAST_STRING_TYPE));
4763 HStringLength* length = new HStringLength(string);
4764 AddInstruction(length);
4765 AddInstruction(new HBoundsCheck(index, length));
4766 return new HStringCharCodeAt(string, index);
4767 }
4768
4769
4723 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, 4770 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
4724 HValue* left, 4771 HValue* left,
4725 HValue* right) { 4772 HValue* right) {
4726 HInstruction* instr = NULL; 4773 HInstruction* instr = NULL;
4727 switch (expr->op()) { 4774 switch (expr->op()) {
4728 case Token::ADD: 4775 case Token::ADD:
4729 instr = new HAdd(left, right); 4776 instr = new HAdd(left, right);
4730 break; 4777 break;
4731 case Token::SUB: 4778 case Token::SUB:
4732 instr = new HSub(left, right); 4779 instr = new HSub(left, right);
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after
5122 } 5169 }
5123 5170
5124 5171
5125 void HGraphBuilder::GenerateSetValueOf(int argument_count, int ast_id) { 5172 void HGraphBuilder::GenerateSetValueOf(int argument_count, int ast_id) {
5126 BAILOUT("inlined runtime function: SetValueOf"); 5173 BAILOUT("inlined runtime function: SetValueOf");
5127 } 5174 }
5128 5175
5129 5176
5130 // Fast support for charCodeAt(n). 5177 // Fast support for charCodeAt(n).
5131 void HGraphBuilder::GenerateStringCharCodeAt(int argument_count, int ast_id) { 5178 void HGraphBuilder::GenerateStringCharCodeAt(int argument_count, int ast_id) {
5132 BAILOUT("inlined runtime function: StringCharCodeAt"); 5179 ASSERT(argument_count == 2);
5180 HValue* index = Pop();
5181 HValue* string = Pop();
5182 HStringCharCodeAt* result = BuildStringCharCodeAt(string, index);
5183 ast_context()->ReturnInstruction(result, ast_id);
5133 } 5184 }
5134 5185
5135 5186
5136 // Fast support for string.charAt(n) and string[n]. 5187 // Fast support for string.charAt(n) and string[n].
5137 void HGraphBuilder::GenerateStringCharFromCode(int argument_count, 5188 void HGraphBuilder::GenerateStringCharFromCode(int argument_count,
5138 int ast_id) { 5189 int ast_id) {
5139 BAILOUT("inlined runtime function: StringCharFromCode"); 5190 BAILOUT("inlined runtime function: StringCharFromCode");
5140 } 5191 }
5141 5192
5142 5193
(...skipping 673 matching lines...) Expand 10 before | Expand all | Expand 10 after
5816 } 5867 }
5817 } 5868 }
5818 5869
5819 #ifdef DEBUG 5870 #ifdef DEBUG
5820 if (graph_ != NULL) graph_->Verify(); 5871 if (graph_ != NULL) graph_->Verify();
5821 if (allocator_ != NULL) allocator_->Verify(); 5872 if (allocator_ != NULL) allocator_->Verify();
5822 #endif 5873 #endif
5823 } 5874 }
5824 5875
5825 } } // namespace v8::internal 5876 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | src/ia32/lithium-ia32.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698