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

Side by Side Diff: src/hydrogen.cc

Issue 6304001: Support StringCharCodeAt in hydrogen/lithium. (Closed)
Patch Set: 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 4066 matching lines...) Expand 10 before | Expand all | Expand 10 after
4113 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) { 4114 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) {
4114 ASSERT(target->IsInlineReturnTarget()); 4115 ASSERT(target->IsInlineReturnTarget());
4115 AddInstruction(new HLeaveInlined); 4116 AddInstruction(new HLeaveInlined);
4116 HEnvironment* outer = last_environment()->outer(); 4117 HEnvironment* outer = last_environment()->outer();
4117 if (return_value != NULL) outer->Push(return_value); 4118 if (return_value != NULL) outer->Push(return_value);
4118 UpdateEnvironment(outer); 4119 UpdateEnvironment(outer);
4119 Goto(target); 4120 Goto(target);
4120 } 4121 }
4121 4122
4122 4123
4123 bool HGraphBuilder::TryMathFunctionInline(Call* expr) { 4124 bool HGraphBuilder::TryInlineBuiltinFunction(Call* expr,
4125 HValue* receiver,
4126 Handle<Map> receiver_map,
4127 CheckType check_type) {
4128 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null());
4124 // Try to inline calls like Math.* as operations in the calling function. 4129 // Try to inline calls like Math.* as operations in the calling function.
4125 if (!expr->target()->shared()->IsBuiltinMathFunction()) return false; 4130 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
4126 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); 4131 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
4127 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 4132 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
4128 switch (id) { 4133 switch (id) {
4134 case kStringCharCodeAt:
4135 if (argument_count == 2 && check_type == STRING_CHECK) {
4136 HValue* index = Pop();
4137 HValue* string = Pop();
4138 ASSERT(!expr->holder().is_null());
4139 AddInstruction(new HCheckPrototypeMaps(
4140 oracle()->GetPrototypeForPrimitiveCheck(check_type),
4141 expr->holder()));
4142 AddInstruction(new HCheckNonSmi(string));
4143 AddInstruction(new HCheckInstanceType(
4144 string, FIRST_STRING_TYPE, LAST_STRING_TYPE));
4145 HStringLength* length = new HStringLength(string);
4146 AddInstruction(length);
4147 AddInstruction(new HBoundsCheck(index, length));
4148 HStringCharCodeAt* result = new HStringCharCodeAt(string, index);
4149 ast_context()->ReturnInstruction(result, expr->id());
4150 return true;
4151 }
4152 break;
4129 case kMathRound: 4153 case kMathRound:
4130 case kMathFloor: 4154 case kMathFloor:
4131 case kMathAbs: 4155 case kMathAbs:
4132 case kMathSqrt: 4156 case kMathSqrt:
4133 case kMathLog: 4157 case kMathLog:
4134 case kMathSin: 4158 case kMathSin:
4135 case kMathCos: 4159 case kMathCos:
4136 if (argument_count == 2) { 4160 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) {
4161 AddCheckConstantFunction(expr, receiver, receiver_map, true);
4137 HValue* argument = Pop(); 4162 HValue* argument = Pop();
4138 Drop(1); // Receiver. 4163 Drop(1); // Receiver.
4139 HUnaryMathOperation* op = new HUnaryMathOperation(argument, id); 4164 HUnaryMathOperation* op = new HUnaryMathOperation(argument, id);
4140 op->set_position(expr->position()); 4165 op->set_position(expr->position());
4141 ast_context()->ReturnInstruction(op, expr->id()); 4166 ast_context()->ReturnInstruction(op, expr->id());
4142 return true; 4167 return true;
4143 } 4168 }
4144 break; 4169 break;
4145 case kMathPow: 4170 case kMathPow:
4146 if (argument_count == 3) { 4171 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) {
4172 AddCheckConstantFunction(expr, receiver, receiver_map, true);
4147 HValue* right = Pop(); 4173 HValue* right = Pop();
4148 HValue* left = Pop(); 4174 HValue* left = Pop();
4149 Pop(); // Pop receiver. 4175 Pop(); // Pop receiver.
4150 HInstruction* result = NULL; 4176 HInstruction* result = NULL;
4151 // Use sqrt() if exponent is 0.5 or -0.5. 4177 // Use sqrt() if exponent is 0.5 or -0.5.
4152 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { 4178 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
4153 double exponent = HConstant::cast(right)->DoubleValue(); 4179 double exponent = HConstant::cast(right)->DoubleValue();
4154 if (exponent == 0.5) { 4180 if (exponent == 0.5) {
4155 result = new HUnaryMathOperation(left, kMathPowHalf); 4181 result = new HUnaryMathOperation(left, kMathPowHalf);
4156 ast_context()->ReturnInstruction(result, expr->id());
4157 return true;
4158 } else if (exponent == -0.5) { 4182 } else if (exponent == -0.5) {
4159 HConstant* double_one = 4183 HConstant* double_one =
4160 new HConstant(Handle<Object>(Smi::FromInt(1)), 4184 new HConstant(Handle<Object>(Smi::FromInt(1)),
4161 Representation::Double()); 4185 Representation::Double());
4162 AddInstruction(double_one); 4186 AddInstruction(double_one);
4163 HUnaryMathOperation* square_root = 4187 HUnaryMathOperation* square_root =
4164 new HUnaryMathOperation(left, kMathPowHalf); 4188 new HUnaryMathOperation(left, kMathPowHalf);
4165 AddInstruction(square_root); 4189 AddInstruction(square_root);
4166 // MathPowHalf doesn't have side effects so there's no need for 4190 // MathPowHalf doesn't have side effects so there's no need for
4167 // an environment simulation here. 4191 // an environment simulation here.
4168 ASSERT(!square_root->HasSideEffects()); 4192 ASSERT(!square_root->HasSideEffects());
4169 result = new HDiv(double_one, square_root); 4193 result = new HDiv(double_one, square_root);
4170 ast_context()->ReturnInstruction(result, expr->id());
4171 return true;
4172 } else if (exponent == 2.0) { 4194 } else if (exponent == 2.0) {
4173 result = new HMul(left, left); 4195 result = new HMul(left, left);
4174 ast_context()->ReturnInstruction(result, expr->id());
4175 return true;
4176 } 4196 }
4177 } else if (right->IsConstant() && 4197 } else if (right->IsConstant() &&
4178 HConstant::cast(right)->HasInteger32Value() && 4198 HConstant::cast(right)->HasInteger32Value() &&
4179 HConstant::cast(right)->Integer32Value() == 2) { 4199 HConstant::cast(right)->Integer32Value() == 2) {
4180 result = new HMul(left, left); 4200 result = new HMul(left, left);
4181 ast_context()->ReturnInstruction(result, expr->id());
4182 return true;
4183 } 4201 }
4184 4202
4185 result = new HPower(left, right); 4203 if (result == NULL) {
4204 result = new HPower(left, right);
4205 }
4186 ast_context()->ReturnInstruction(result, expr->id()); 4206 ast_context()->ReturnInstruction(result, expr->id());
4187 return true; 4207 return true;
4188 } 4208 }
4189 break; 4209 break;
4190 default: 4210 default:
4191 // Not yet supported for inlining. 4211 // Not yet supported for inlining.
4192 break; 4212 break;
4193 } 4213 }
4194 return false; 4214 return false;
4195 } 4215 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
4230 expr->GetReceiverTypes()->first(), 4250 expr->GetReceiverTypes()->first(),
4231 true); 4251 true);
4232 HInstruction* result = 4252 HInstruction* result =
4233 new HApplyArguments(function, receiver, length, elements); 4253 new HApplyArguments(function, receiver, length, elements);
4234 result->set_position(expr->position()); 4254 result->set_position(expr->position());
4235 ast_context()->ReturnInstruction(result, expr->id()); 4255 ast_context()->ReturnInstruction(result, expr->id());
4236 return true; 4256 return true;
4237 } 4257 }
4238 4258
4239 4259
4260 static bool HasCustomCallGenerator(Handle<JSFunction> function) {
4261 SharedFunctionInfo* info = function->shared();
4262 return info->HasBuiltinFunctionId() &&
4263 CallStubCompiler::HasCustomCallGenerator(info->builtin_function_id());
4264 }
4265
4266
4240 void HGraphBuilder::VisitCall(Call* expr) { 4267 void HGraphBuilder::VisitCall(Call* expr) {
4241 Expression* callee = expr->expression(); 4268 Expression* callee = expr->expression();
4242 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 4269 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
4243 HCall* call = NULL; 4270 HCall* call = NULL;
4244 4271
4245 Property* prop = callee->AsProperty(); 4272 Property* prop = callee->AsProperty();
4246 if (prop != NULL) { 4273 if (prop != NULL) {
4247 if (!prop->key()->IsPropertyName()) { 4274 if (!prop->key()->IsPropertyName()) {
4248 // Keyed function call. 4275 // Keyed function call.
4249 VisitArgument(prop->obj()); 4276 VisitArgument(prop->obj());
(...skipping 26 matching lines...) Expand all
4276 HValue* receiver = VisitArgument(prop->obj()); 4303 HValue* receiver = VisitArgument(prop->obj());
4277 CHECK_BAILOUT; 4304 CHECK_BAILOUT;
4278 VisitArgumentList(expr->arguments()); 4305 VisitArgumentList(expr->arguments());
4279 CHECK_BAILOUT; 4306 CHECK_BAILOUT;
4280 4307
4281 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 4308 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4282 4309
4283 expr->RecordTypeFeedback(oracle()); 4310 expr->RecordTypeFeedback(oracle());
4284 ZoneMapList* types = expr->GetReceiverTypes(); 4311 ZoneMapList* types = expr->GetReceiverTypes();
4285 4312
4286 if (expr->IsMonomorphic() && expr->check_type() == RECEIVER_MAP_CHECK) { 4313 if (expr->IsMonomorphic()) {
4287 AddCheckConstantFunction(expr, receiver, types->first(), true); 4314 Handle<Map> receiver_map =
4288 4315 (types == NULL) ? Handle<Map>::null() : types->first();
4289 if (TryMathFunctionInline(expr)) { 4316 if (TryInlineBuiltinFunction(expr,
4317 receiver,
4318 receiver_map,
4319 expr->check_type())) {
4290 return; 4320 return;
4291 } else if (TryInline(expr)) {
4292 if (subgraph()->HasExit()) {
4293 HValue* return_value = Pop();
4294 // If we inlined a function in a test context then we need to emit
4295 // a simulate here to shadow the ones at the end of the
4296 // predecessor blocks. Those environments contain the return
4297 // value on top and do not correspond to any actual state of the
4298 // unoptimized code.
4299 if (ast_context()->IsEffect()) AddSimulate(expr->id());
4300 ast_context()->ReturnValue(return_value);
4301 }
4302 return;
4303 } else {
4304 // Check for bailout, as the TryInline call in the if condition above
4305 // might return false due to bailout during hydrogen processing.
4306 CHECK_BAILOUT;
4307 call = new HCallConstantFunction(expr->target(), argument_count);
4308 } 4321 }
4309 4322
4323 if (HasCustomCallGenerator(expr->target()) ||
4324 expr->check_type() != RECEIVER_MAP_CHECK) {
4325 // When the target has a custom call IC generator, use the IC,
4326 // because it is likely to generate better code. Also use the
4327 // IC when a primitive receiver check is required.
4328 call = new HCallNamed(name, argument_count);
4329 } else {
4330 AddCheckConstantFunction(expr, receiver, receiver_map, true);
4331
4332 if (TryInline(expr)) {
4333 if (subgraph()->HasExit()) {
4334 HValue* return_value = Pop();
4335 // If we inlined a function in a test context then we need to emit
4336 // a simulate here to shadow the ones at the end of the
4337 // predecessor blocks. Those environments contain the return
4338 // value on top and do not correspond to any actual state of the
4339 // unoptimized code.
4340 if (ast_context()->IsEffect()) AddSimulate(expr->id());
4341 ast_context()->ReturnValue(return_value);
4342 }
4343 return;
4344 } else {
4345 // Check for bailout, as the TryInline call in the if condition above
4346 // might return false due to bailout during hydrogen processing.
4347 CHECK_BAILOUT;
4348 call = new HCallConstantFunction(expr->target(), argument_count);
4349 }
4350 }
4310 } else if (types != NULL && types->length() > 1) { 4351 } else if (types != NULL && types->length() > 1) {
4311 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); 4352 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK);
4312 HandlePolymorphicCallNamed(expr, receiver, types, name); 4353 HandlePolymorphicCallNamed(expr, receiver, types, name);
4313 return; 4354 return;
4314 4355
4315 } else { 4356 } else {
4316 call = new HCallNamed(name, argument_count); 4357 call = new HCallNamed(name, argument_count);
4317 } 4358 }
4318 4359
4319 } else { 4360 } else {
(...skipping 1470 matching lines...) Expand 10 before | Expand all | Expand 10 after
5790 } 5831 }
5791 } 5832 }
5792 5833
5793 #ifdef DEBUG 5834 #ifdef DEBUG
5794 if (graph_ != NULL) graph_->Verify(); 5835 if (graph_ != NULL) graph_->Verify();
5795 if (allocator_ != NULL) allocator_->Verify(); 5836 if (allocator_ != NULL) allocator_->Verify();
5796 #endif 5837 #endif
5797 } 5838 }
5798 5839
5799 } } // namespace v8::internal 5840 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | src/hydrogen-instructions.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698