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

Side by Side Diff: net/tools/balsa/balsa_frame.cc

Issue 383543003: Port the __SSE2__ code to Visual C++. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add a comment about MSVC predefined macro _M_IX86_FP. Created 6 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 | « no previous file | 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium 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 "net/tools/balsa/balsa_frame.h" 5 #include "net/tools/balsa/balsa_frame.h"
6 6
7 // Visual C++ defines _M_IX86_FP as 2 if the /arch:SSE2 compiler option is
8 // specified.
9 #if !defined(__SSE2__) && _M_IX86_FP == 2
10 #define __SSE2__ 1
11 #endif
12
7 #include <assert.h> 13 #include <assert.h>
8 #if __SSE2__ 14 #if __SSE2__
9 #include <emmintrin.h> 15 #include <emmintrin.h>
10 #endif // __SSE2__ 16 #endif // __SSE2__
11 17
12 #include <limits> 18 #include <limits>
13 #include <string> 19 #include <string>
14 #include <utility> 20 #include <utility>
15 #include <vector> 21 #include <vector>
16 22
17 #include "base/logging.h" 23 #include "base/logging.h"
18 #include "base/port.h" 24 #include "base/port.h"
19 #include "base/strings/string_piece.h" 25 #include "base/strings/string_piece.h"
20 #include "net/tools/balsa/balsa_enums.h" 26 #include "net/tools/balsa/balsa_enums.h"
21 #include "net/tools/balsa/balsa_headers.h" 27 #include "net/tools/balsa/balsa_headers.h"
22 #include "net/tools/balsa/balsa_visitor_interface.h" 28 #include "net/tools/balsa/balsa_visitor_interface.h"
23 #include "net/tools/balsa/buffer_interface.h" 29 #include "net/tools/balsa/buffer_interface.h"
24 #include "net/tools/balsa/simple_buffer.h" 30 #include "net/tools/balsa/simple_buffer.h"
25 #include "net/tools/balsa/split.h" 31 #include "net/tools/balsa/split.h"
26 #include "net/tools/balsa/string_piece_utils.h" 32 #include "net/tools/balsa/string_piece_utils.h"
27 33
28 #if defined(COMPILER_MSVC) 34 #if defined(COMPILER_MSVC)
35 #include <intrin.h>
29 #include <string.h> 36 #include <string.h>
37
38 #pragma intrinsic(_BitScanForward)
39
40 static int ffs(int i) {
41 unsigned long index;
42 return _BitScanForward(&index, i) ? index + 1 : 0;
43 }
44
30 #define strncasecmp _strnicmp 45 #define strncasecmp _strnicmp
31 #else 46 #else
32 #include <strings.h> 47 #include <strings.h>
33 #endif 48 #endif
34 49
35 namespace net { 50 namespace net {
36 51
37 // Constants holding some header names for headers which can affect the way the 52 // Constants holding some header names for headers which can affect the way the
38 // HTTP message is framed, and so must be processed specially: 53 // HTTP message is framed, and so must be processed specially:
39 static const char kContentLength[] = "content-length"; 54 static const char kContentLength[] = "content-length";
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 DCHECK_GE(current_header_line->last_char_idx, 511 DCHECK_GE(current_header_line->last_char_idx,
497 current_header_line->value_begin_idx); 512 current_header_line->value_begin_idx);
498 } 513 }
499 514
500 inline void BalsaFrame::FindColonsAndParseIntoKeyValue() { 515 inline void BalsaFrame::FindColonsAndParseIntoKeyValue() {
501 DCHECK(!lines_.empty()); 516 DCHECK(!lines_.empty());
502 const char* stream_begin = headers_->OriginalHeaderStreamBegin(); 517 const char* stream_begin = headers_->OriginalHeaderStreamBegin();
503 // The last line is always just a newline (and is uninteresting). 518 // The last line is always just a newline (and is uninteresting).
504 const Lines::size_type lines_size_m1 = lines_.size() - 1; 519 const Lines::size_type lines_size_m1 = lines_.size() - 1;
505 #if __SSE2__ 520 #if __SSE2__
506 const __v16qi colons = { ':', ':', ':', ':', ':', ':', ':', ':', 521 const __m128i colons = _mm_set1_epi8(':');
507 ':', ':', ':', ':', ':', ':', ':', ':'};
508 const char* header_lines_end_m16 = headers_->OriginalHeaderStreamEnd() - 16; 522 const char* header_lines_end_m16 = headers_->OriginalHeaderStreamEnd() - 16;
509 #endif // __SSE2__ 523 #endif // __SSE2__
510 const char* current = stream_begin + lines_[1].first; 524 const char* current = stream_begin + lines_[1].first;
511 // This code is a bit more subtle than it may appear at first glance. 525 // This code is a bit more subtle than it may appear at first glance.
512 // This code looks for a colon in the current line... but it also looks 526 // This code looks for a colon in the current line... but it also looks
513 // beyond the current line. If there is no colon in the current line, then 527 // beyond the current line. If there is no colon in the current line, then
514 // for each subsequent line (until the colon which -has- been found is 528 // for each subsequent line (until the colon which -has- been found is
515 // associated with a line), no searching for a colon will be performed. In 529 // associated with a line), no searching for a colon will be performed. In
516 // this way, we minimize the amount of bytes we have scanned for a colon. 530 // this way, we minimize the amount of bytes we have scanned for a colon.
517 for (Lines::size_type i = 1; i < lines_size_m1;) { 531 for (Lines::size_type i = 1; i < lines_size_m1;) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
568 // When this condition is true, the last detected colon was part of a 582 // When this condition is true, the last detected colon was part of a
569 // previous line. We reset to the beginning of the line as we don't care 583 // previous line. We reset to the beginning of the line as we don't care
570 // about the presence of any colon before the beginning of the current 584 // about the presence of any colon before the beginning of the current
571 // line. 585 // line.
572 current = line_begin; 586 current = line_begin;
573 } 587 }
574 #if __SSE2__ 588 #if __SSE2__
575 while (current < header_lines_end_m16) { 589 while (current < header_lines_end_m16) {
576 __m128i header_bytes = 590 __m128i header_bytes =
577 _mm_loadu_si128(reinterpret_cast<const __m128i *>(current)); 591 _mm_loadu_si128(reinterpret_cast<const __m128i *>(current));
578 __m128i colon_cmp = 592 __m128i colon_cmp = _mm_cmpeq_epi8(header_bytes, colons);
579 _mm_cmpeq_epi8(header_bytes, reinterpret_cast<__m128i>(colons));
580 int colon_msk = _mm_movemask_epi8(colon_cmp); 593 int colon_msk = _mm_movemask_epi8(colon_cmp);
581 if (colon_msk == 0) { 594 if (colon_msk == 0) {
582 current += 16; 595 current += 16;
583 continue; 596 continue;
584 } 597 }
585 current += (ffs(colon_msk) - 1); 598 current += (ffs(colon_msk) - 1);
586 if (current > line_end) { 599 if (current > line_end) {
587 break; 600 break;
588 } 601 }
589 goto found_colon; 602 goto found_colon;
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after
975 } 988 }
976 ++message_current; 989 ++message_current;
977 } while (message_current < message_end); 990 } while (message_current < message_end);
978 goto bottom; // this is necessary to skip 'last_char_was_slash_r' checks 991 goto bottom; // this is necessary to skip 'last_char_was_slash_r' checks
979 } else { 992 } else {
980 read_real_message: 993 read_real_message:
981 // Note that SSE2 can be enabled on certain piii platforms. 994 // Note that SSE2 can be enabled on certain piii platforms.
982 #if __SSE2__ 995 #if __SSE2__
983 { 996 {
984 const char* const message_end_m16 = message_end - 16; 997 const char* const message_end_m16 = message_end - 16;
985 __v16qi newlines = { '\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n', 998 __m128i newlines = _mm_set1_epi8('\n');
986 '\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n' };
987 while (message_current < message_end_m16) { 999 while (message_current < message_end_m16) {
988 // What this does (using compiler intrinsics): 1000 // What this does (using compiler intrinsics):
989 // 1001 //
990 // Load 16 '\n's into an xmm register 1002 // Load 16 '\n's into an xmm register
991 // Load 16 bytes of currennt message into an xmm register 1003 // Load 16 bytes of currennt message into an xmm register
992 // Do byte-wise equals on those two xmm registers 1004 // Do byte-wise equals on those two xmm registers
993 // Take the first bit of each byte, and put that into the first 1005 // Take the first bit of each byte, and put that into the first
994 // 16 bits of a mask 1006 // 16 bits of a mask
995 // If the mask is zero, no '\n' found. increment by 16 and try again 1007 // If the mask is zero, no '\n' found. increment by 16 and try again
996 // Else scan forward to find the first set bit. 1008 // Else scan forward to find the first set bit.
997 // Increment current by the index of the first set bit 1009 // Increment current by the index of the first set bit
998 // (ffs returns index of first set bit + 1) 1010 // (ffs returns index of first set bit + 1)
999 __m128i msg_bytes = 1011 __m128i msg_bytes =
1000 _mm_loadu_si128(const_cast<__m128i *>( 1012 _mm_loadu_si128(const_cast<__m128i *>(
1001 reinterpret_cast<const __m128i *>(message_current))); 1013 reinterpret_cast<const __m128i *>(message_current)));
1002 __m128i newline_cmp = 1014 __m128i newline_cmp = _mm_cmpeq_epi8(msg_bytes, newlines);
1003 _mm_cmpeq_epi8(msg_bytes, reinterpret_cast<__m128i>(newlines));
1004 int newline_msk = _mm_movemask_epi8(newline_cmp); 1015 int newline_msk = _mm_movemask_epi8(newline_cmp);
1005 if (newline_msk == 0) { 1016 if (newline_msk == 0) {
1006 message_current += 16; 1017 message_current += 16;
1007 continue; 1018 continue;
1008 } 1019 }
1009 message_current += (ffs(newline_msk) - 1); 1020 message_current += (ffs(newline_msk) - 1);
1010 const size_t relative_idx = message_current - message_start; 1021 const size_t relative_idx = message_current - message_start;
1011 const size_t message_current_idx = 1 + base_idx + relative_idx; 1022 const size_t message_current_idx = 1 + base_idx + relative_idx;
1012 lines_.push_back(std::make_pair(last_slash_n_idx_, 1023 lines_.push_back(std::make_pair(last_slash_n_idx_,
1013 message_current_idx)); 1024 message_current_idx));
(...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after
1556 << "$$$$$$$$$$$$$$$" 1567 << "$$$$$$$$$$$$$$$"
1557 << " consumed: " << (current - input); 1568 << " consumed: " << (current - input);
1558 if (Error()) { 1569 if (Error()) {
1559 LOG(INFO) << BalsaFrameEnums::ErrorCodeToString(ErrorCode()); 1570 LOG(INFO) << BalsaFrameEnums::ErrorCodeToString(ErrorCode());
1560 } 1571 }
1561 #endif // DEBUGFRAMER 1572 #endif // DEBUGFRAMER
1562 return current - input; 1573 return current - input;
1563 } 1574 }
1564 1575
1565 } // namespace net 1576 } // namespace net
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698