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

Side by Side Diff: src/x64/codegen-x64.cc

Issue 2897013: Avoid a smi check when comparing an unknown to a constant smi for equality on... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « src/x64/codegen-x64.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 1984 matching lines...) Expand 10 before | Expand all | Expand 10 after
1995 if (right_side.is_constant()) { 1995 if (right_side.is_constant()) {
1996 right_side_constant_smi = right_side.handle()->IsSmi(); 1996 right_side_constant_smi = right_side.handle()->IsSmi();
1997 right_side_constant_null = right_side.handle()->IsNull(); 1997 right_side_constant_null = right_side.handle()->IsNull();
1998 right_side_constant_1_char_string = 1998 right_side_constant_1_char_string =
1999 (right_side.handle()->IsString() && 1999 (right_side.handle()->IsString() &&
2000 String::cast(*right_side.handle())->length() == 1 && 2000 String::cast(*right_side.handle())->length() == 1 &&
2001 String::cast(*right_side.handle())->IsAsciiRepresentation()); 2001 String::cast(*right_side.handle())->IsAsciiRepresentation());
2002 } 2002 }
2003 2003
2004 if (left_side_constant_smi || right_side_constant_smi) { 2004 if (left_side_constant_smi || right_side_constant_smi) {
2005 if (left_side_constant_smi && right_side_constant_smi) { 2005 bool is_loop_condition = (node->AsExpression() != NULL) &&
2006 // Trivial case, comparing two constants. 2006 node->AsExpression()->is_loop_condition();
2007 int left_value = Smi::cast(*left_side.handle())->value(); 2007 ConstantSmiComparison(cc, strict, dest, &left_side, &right_side,
2008 int right_value = Smi::cast(*right_side.handle())->value(); 2008 left_side_constant_smi, right_side_constant_smi,
2009 switch (cc) { 2009 is_loop_condition);
2010 case less:
2011 dest->Goto(left_value < right_value);
2012 break;
2013 case equal:
2014 dest->Goto(left_value == right_value);
2015 break;
2016 case greater_equal:
2017 dest->Goto(left_value >= right_value);
2018 break;
2019 default:
2020 UNREACHABLE();
2021 }
2022 } else {
2023 // Only one side is a constant Smi.
2024 // If left side is a constant Smi, reverse the operands.
2025 // Since one side is a constant Smi, conversion order does not matter.
2026 if (left_side_constant_smi) {
2027 Result temp = left_side;
2028 left_side = right_side;
2029 right_side = temp;
2030 cc = ReverseCondition(cc);
2031 // This may re-introduce greater or less_equal as the value of cc.
2032 // CompareStub and the inline code both support all values of cc.
2033 }
2034 // Implement comparison against a constant Smi, inlining the case
2035 // where both sides are Smis.
2036 left_side.ToRegister();
2037 Register left_reg = left_side.reg();
2038 Handle<Object> right_val = right_side.handle();
2039
2040 // Here we split control flow to the stub call and inlined cases
2041 // before finally splitting it to the control destination. We use
2042 // a jump target and branching to duplicate the virtual frame at
2043 // the first split. We manually handle the off-frame references
2044 // by reconstituting them on the non-fall-through path.
2045 JumpTarget is_smi;
2046
2047 if (left_side.is_smi()) {
2048 if (FLAG_debug_code) {
2049 __ AbortIfNotSmi(left_side.reg());
2050 }
2051 } else {
2052 Condition left_is_smi = masm_->CheckSmi(left_side.reg());
2053 is_smi.Branch(left_is_smi);
2054
2055 bool is_loop_condition = (node->AsExpression() != NULL) &&
2056 node->AsExpression()->is_loop_condition();
2057 if (!is_loop_condition && right_val->IsSmi()) {
2058 // Right side is a constant smi and left side has been checked
2059 // not to be a smi.
2060 JumpTarget not_number;
2061 __ Cmp(FieldOperand(left_reg, HeapObject::kMapOffset),
2062 Factory::heap_number_map());
2063 not_number.Branch(not_equal, &left_side);
2064 __ movsd(xmm1,
2065 FieldOperand(left_reg, HeapNumber::kValueOffset));
2066 int value = Smi::cast(*right_val)->value();
2067 if (value == 0) {
2068 __ xorpd(xmm0, xmm0);
2069 } else {
2070 Result temp = allocator()->Allocate();
2071 __ movl(temp.reg(), Immediate(value));
2072 __ cvtlsi2sd(xmm0, temp.reg());
2073 temp.Unuse();
2074 }
2075 __ ucomisd(xmm1, xmm0);
2076 // Jump to builtin for NaN.
2077 not_number.Branch(parity_even, &left_side);
2078 left_side.Unuse();
2079 dest->true_target()->Branch(DoubleCondition(cc));
2080 dest->false_target()->Jump();
2081 not_number.Bind(&left_side);
2082 }
2083
2084 // Setup and call the compare stub.
2085 CompareStub stub(cc, strict, kCantBothBeNaN);
2086 Result result = frame_->CallStub(&stub, &left_side, &right_side);
2087 result.ToRegister();
2088 __ testq(result.reg(), result.reg());
2089 result.Unuse();
2090 dest->true_target()->Branch(cc);
2091 dest->false_target()->Jump();
2092
2093 is_smi.Bind();
2094 }
2095
2096 left_side = Result(left_reg);
2097 right_side = Result(right_val);
2098 // Test smi equality and comparison by signed int comparison.
2099 // Both sides are smis, so we can use an Immediate.
2100 __ SmiCompare(left_side.reg(), Smi::cast(*right_side.handle()));
2101 left_side.Unuse();
2102 right_side.Unuse();
2103 dest->Split(cc);
2104 }
2105 } else if (cc == equal && 2010 } else if (cc == equal &&
2106 (left_side_constant_null || right_side_constant_null)) { 2011 (left_side_constant_null || right_side_constant_null)) {
2107 // To make null checks efficient, we check if either the left side or 2012 // To make null checks efficient, we check if either the left side or
2108 // the right side is the constant 'null'. 2013 // the right side is the constant 'null'.
2109 // If so, we optimize the code by inlining a null check instead of 2014 // If so, we optimize the code by inlining a null check instead of
2110 // calling the (very) general runtime routine for checking equality. 2015 // calling the (very) general runtime routine for checking equality.
2111 Result operand = left_side_constant_null ? right_side : left_side; 2016 Result operand = left_side_constant_null ? right_side : left_side;
2112 right_side.Unuse(); 2017 right_side.Unuse();
2113 left_side.Unuse(); 2018 left_side.Unuse();
2114 operand.ToRegister(); 2019 operand.ToRegister();
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
2359 right_side = Result(right_reg); 2264 right_side = Result(right_reg);
2360 __ SmiCompare(left_side.reg(), right_side.reg()); 2265 __ SmiCompare(left_side.reg(), right_side.reg());
2361 right_side.Unuse(); 2266 right_side.Unuse();
2362 left_side.Unuse(); 2267 left_side.Unuse();
2363 dest->Split(cc); 2268 dest->Split(cc);
2364 } 2269 }
2365 } 2270 }
2366 } 2271 }
2367 2272
2368 2273
2274 void CodeGenerator::ConstantSmiComparison(Condition cc,
2275 bool strict,
2276 ControlDestination* dest,
2277 Result* left_side,
2278 Result* right_side,
2279 bool left_side_constant_smi,
2280 bool right_side_constant_smi,
2281 bool is_loop_condition) {
2282 if (left_side_constant_smi && right_side_constant_smi) {
2283 // Trivial case, comparing two constants.
2284 int left_value = Smi::cast(*left_side->handle())->value();
2285 int right_value = Smi::cast(*right_side->handle())->value();
2286 switch (cc) {
2287 case less:
2288 dest->Goto(left_value < right_value);
2289 break;
2290 case equal:
2291 dest->Goto(left_value == right_value);
2292 break;
2293 case greater_equal:
2294 dest->Goto(left_value >= right_value);
2295 break;
2296 default:
2297 UNREACHABLE();
2298 }
2299 } else {
2300 // Only one side is a constant Smi.
2301 // If left side is a constant Smi, reverse the operands.
2302 // Since one side is a constant Smi, conversion order does not matter.
2303 if (left_side_constant_smi) {
2304 Result* temp = left_side;
2305 left_side = right_side;
2306 right_side = temp;
2307 cc = ReverseCondition(cc);
2308 // This may re-introduce greater or less_equal as the value of cc.
2309 // CompareStub and the inline code both support all values of cc.
2310 }
2311 // Implement comparison against a constant Smi, inlining the case
2312 // where both sides are Smis.
2313 left_side->ToRegister();
2314 Register left_reg = left_side->reg();
2315 Smi* constant_smi = Smi::cast(*right_side->handle());
2316
2317 if (left_side->is_smi()) {
2318 if (FLAG_debug_code) {
2319 __ AbortIfNotSmi(left_reg);
2320 }
2321 // Test smi equality and comparison by signed int comparison.
2322 // Both sides are smis, so we can use an Immediate.
2323 __ SmiCompare(left_reg, constant_smi);
2324 left_side->Unuse();
2325 right_side->Unuse();
2326 dest->Split(cc);
2327 } else {
2328 // Only the case where the left side could possibly be a non-smi is left.
2329 JumpTarget is_smi;
2330 if (cc == equal) {
2331 // We can do the equality comparison before the smi check.
2332 __ SmiCompare(left_reg, constant_smi);
2333 dest->true_target()->Branch(equal);
2334 Condition left_is_smi = masm_->CheckSmi(left_reg);
2335 dest->false_target()->Branch(left_is_smi);
2336 } else {
2337 // Do the smi check, then the comparison.
2338 Condition left_is_smi = masm_->CheckSmi(left_reg);
2339 is_smi.Branch(left_is_smi, left_side, right_side);
2340 }
2341
2342 // Jump or fall through to here if we are comparing a non-smi to a
2343 // constant smi. If the non-smi is a heap number and this is not
2344 // a loop condition, inline the floating point code.
2345 if (!is_loop_condition) {
2346 // Right side is a constant smi and left side has been checked
2347 // not to be a smi.
2348 JumpTarget not_number;
2349 __ Cmp(FieldOperand(left_reg, HeapObject::kMapOffset),
2350 Factory::heap_number_map());
2351 not_number.Branch(not_equal, left_side);
2352 __ movsd(xmm1,
2353 FieldOperand(left_reg, HeapNumber::kValueOffset));
2354 int value = constant_smi->value();
2355 if (value == 0) {
2356 __ xorpd(xmm0, xmm0);
2357 } else {
2358 Result temp = allocator()->Allocate();
2359 __ movl(temp.reg(), Immediate(value));
2360 __ cvtlsi2sd(xmm0, temp.reg());
2361 temp.Unuse();
2362 }
2363 __ ucomisd(xmm1, xmm0);
2364 // Jump to builtin for NaN.
2365 not_number.Branch(parity_even, left_side);
2366 left_side->Unuse();
2367 dest->true_target()->Branch(DoubleCondition(cc));
2368 dest->false_target()->Jump();
2369 not_number.Bind(left_side);
2370 }
2371
2372 // Setup and call the compare stub.
2373 CompareStub stub(cc, strict, kCantBothBeNaN);
2374 Result result = frame_->CallStub(&stub, left_side, right_side);
2375 result.ToRegister();
2376 __ testq(result.reg(), result.reg());
2377 result.Unuse();
2378 if (cc == equal) {
2379 dest->Split(cc);
2380 } else {
2381 dest->true_target()->Branch(cc);
2382 dest->false_target()->Jump();
2383
2384 // It is important for performance for this case to be at the end.
2385 is_smi.Bind(left_side, right_side);
2386 __ SmiCompare(left_reg, constant_smi);
2387 left_side->Unuse();
2388 right_side->Unuse();
2389 dest->Split(cc);
2390 }
2391 }
2392 }
2393 }
2394
2395
2369 // Load a comparison operand into into a XMM register. Jump to not_numbers jump 2396 // Load a comparison operand into into a XMM register. Jump to not_numbers jump
2370 // target passing the left and right result if the operand is not a number. 2397 // target passing the left and right result if the operand is not a number.
2371 static void LoadComparisonOperand(MacroAssembler* masm_, 2398 static void LoadComparisonOperand(MacroAssembler* masm_,
2372 Result* operand, 2399 Result* operand,
2373 XMMRegister xmm_reg, 2400 XMMRegister xmm_reg,
2374 Result* left_side, 2401 Result* left_side,
2375 Result* right_side, 2402 Result* right_side,
2376 JumpTarget* not_numbers) { 2403 JumpTarget* not_numbers) {
2377 Label done; 2404 Label done;
2378 if (operand->type_info().IsDouble()) { 2405 if (operand->type_info().IsDouble()) {
(...skipping 9678 matching lines...) Expand 10 before | Expand all | Expand 10 after
12057 #undef __ 12084 #undef __
12058 12085
12059 void RecordWriteStub::Generate(MacroAssembler* masm) { 12086 void RecordWriteStub::Generate(MacroAssembler* masm) {
12060 masm->RecordWriteHelper(object_, addr_, scratch_); 12087 masm->RecordWriteHelper(object_, addr_, scratch_);
12061 masm->ret(0); 12088 masm->ret(0);
12062 } 12089 }
12063 12090
12064 } } // namespace v8::internal 12091 } } // namespace v8::internal
12065 12092
12066 #endif // V8_TARGET_ARCH_X64 12093 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/codegen-x64.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698