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

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

Issue 6469052: x64: Implement regexp literals and string CharCodeAt in lithium backend. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 10 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/lithium-codegen-x64.h ('k') | src/x64/lithium-x64.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 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 2291 matching lines...) Expand 10 before | Expand all | Expand 10 after
2302 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { 2302 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
2303 ASSERT(ToRegister(instr->object()).is(rdx)); 2303 ASSERT(ToRegister(instr->object()).is(rdx));
2304 ASSERT(ToRegister(instr->key()).is(rcx)); 2304 ASSERT(ToRegister(instr->key()).is(rcx));
2305 ASSERT(ToRegister(instr->value()).is(rax)); 2305 ASSERT(ToRegister(instr->value()).is(rax));
2306 2306
2307 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 2307 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
2308 CallCode(ic, RelocInfo::CODE_TARGET, instr); 2308 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2309 } 2309 }
2310 2310
2311 2311
2312 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
2313 class DeferredStringCharCodeAt: public LDeferredCode {
2314 public:
2315 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr)
2316 : LDeferredCode(codegen), instr_(instr) { }
2317 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); }
2318 private:
2319 LStringCharCodeAt* instr_;
2320 };
2321
2322 Register string = ToRegister(instr->string());
2323 Register index = no_reg;
2324 int const_index = -1;
2325 if (instr->index()->IsConstantOperand()) {
2326 const_index = ToInteger32(LConstantOperand::cast(instr->index()));
2327 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
2328 if (!Smi::IsValid(const_index)) {
2329 // Guaranteed to be out of bounds because of the assert above.
2330 // So the bounds check that must dominate this instruction must
2331 // have deoptimized already.
2332 if (FLAG_debug_code) {
2333 __ Abort("StringCharCodeAt: out of bounds index.");
2334 }
2335 // No code needs to be generated.
2336 return;
2337 }
2338 } else {
2339 index = ToRegister(instr->index());
2340 }
2341 Register result = ToRegister(instr->result());
2342
2343 DeferredStringCharCodeAt* deferred =
2344 new DeferredStringCharCodeAt(this, instr);
2345
2346 NearLabel flat_string, ascii_string, done;
2347
2348 // Fetch the instance type of the receiver into result register.
2349 __ movq(result, FieldOperand(string, HeapObject::kMapOffset));
2350 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset));
2351
2352 // We need special handling for non-flat strings.
Lasse Reichstein 2011/02/18 13:22:25 ... special handling for non-sequential strings. (
Mads Ager (chromium) 2011/02/18 13:58:47 Done.
2353 STATIC_ASSERT(kSeqStringTag == 0);
2354 __ testb(result, Immediate(kStringRepresentationMask));
2355 __ j(zero, &flat_string);
2356
2357 // Handle non-flat strings.
2358 __ testb(result, Immediate(kIsConsStringMask));
2359 __ j(zero, deferred->entry());
2360
2361 // ConsString.
2362 // Check whether the right hand side is the empty string (i.e. if
2363 // this is really a flat string in a cons string). If that is not
2364 // the case we would rather go to the runtime system now to flatten
2365 // the string.
2366 __ CompareRoot(FieldOperand(string, ConsString::kSecondOffset),
2367 Heap::kEmptyStringRootIndex);
2368 __ j(not_equal, deferred->entry());
2369 // Get the first of the two strings and load its instance type.
2370 __ movq(string, FieldOperand(string, ConsString::kFirstOffset));
2371 __ movq(result, FieldOperand(string, HeapObject::kMapOffset));
2372 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset));
2373 // If the first cons component is also non-flat, then go to runtime.
2374 STATIC_ASSERT(kSeqStringTag == 0);
2375 __ testb(result, Immediate(kStringRepresentationMask));
2376 __ j(not_zero, deferred->entry());
2377
2378 // Check for 1-byte or 2-byte string.
Lasse Reichstein 2011/02/18 13:22:25 You call it 1-byte string here and ASCII string be
Mads Ager (chromium) 2011/02/18 13:58:47 Done.
2379 __ bind(&flat_string);
2380 STATIC_ASSERT(kAsciiStringTag != 0);
2381 __ testb(result, Immediate(kStringEncodingMask));
2382 __ j(not_zero, &ascii_string);
2383
2384 // 2-byte string.
2385 // Load the 2-byte character code into the result register.
2386 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
2387 if (instr->index()->IsConstantOperand()) {
2388 __ movzxwl(result,
2389 FieldOperand(string,
2390 SeqTwoByteString::kHeaderSize + 2 * const_index));
Lasse Reichstein 2011/02/18 13:22:25 Use kUC16Size instead of 2.
Mads Ager (chromium) 2011/02/18 13:58:47 Done.
2391 } else {
2392 __ movzxwl(result, FieldOperand(string,
2393 index,
2394 times_2,
2395 SeqTwoByteString::kHeaderSize));
2396 }
2397 __ jmp(&done);
2398
2399 // ASCII string.
2400 // Load the byte into the result register.
2401 __ bind(&ascii_string);
2402 if (instr->index()->IsConstantOperand()) {
2403 __ movzxbl(result, FieldOperand(string,
2404 SeqAsciiString::kHeaderSize + const_index));
2405 } else {
2406 __ movzxbl(result, FieldOperand(string,
2407 index,
2408 times_1,
2409 SeqAsciiString::kHeaderSize));
2410 }
2411 __ bind(&done);
2412 __ bind(deferred->exit());
2413 }
2414
2415
2416 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
2417 Register string = ToRegister(instr->string());
2418 Register result = ToRegister(instr->result());
2419
2420 // TODO(3095996): Get rid of this. For now, we need to make the
2421 // result register contain a valid pointer because it is already
2422 // contained in the register pointer map.
2423 __ Set(result, 0);
2424
2425 __ PushSafepointRegisters();
2426 __ push(string);
2427 // Push the index as a smi. This is safe because of the checks in
2428 // DoStringCharCodeAt above.
2429 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
2430 if (instr->index()->IsConstantOperand()) {
2431 int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
2432 __ Push(Smi::FromInt(const_index));
2433 } else {
2434 Register index = ToRegister(instr->index());
2435 __ Integer32ToSmi(index, index);
2436 __ push(index);
2437 }
2438 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2439 __ CallRuntimeSaveDoubles(Runtime::kStringCharCodeAt);
2440 RecordSafepointWithRegisters(
2441 instr->pointer_map(), 2, Safepoint::kNoDeoptimizationIndex);
2442 if (FLAG_debug_code) {
2443 __ AbortIfNotSmi(rax);
2444 }
2445 __ Integer32ToSmi(rax, rax);
Lasse Reichstein 2011/02/18 13:22:25 Should be SmiToInteger32.
Mads Ager (chromium) 2011/02/18 13:58:47 Whoops! Done.
2446 __ movq(Operand(rsp, Register::ToRspIndexForPushAll(result) * kPointerSize),
2447 rax);
2448 __ PopSafepointRegisters();
Lasse Reichstein 2011/02/18 13:22:25 We could make an alternative version: PopSafepoint
Mads Ager (chromium) 2011/02/18 13:58:47 Don't think it will. Will leave that for a separat
2449 }
2450
2451
2312 void LCodeGen::DoStringLength(LStringLength* instr) { 2452 void LCodeGen::DoStringLength(LStringLength* instr) {
2313 Register string = ToRegister(instr->string()); 2453 Register string = ToRegister(instr->string());
2314 Register result = ToRegister(instr->result()); 2454 Register result = ToRegister(instr->result());
2315 __ movq(result, FieldOperand(string, String::kLengthOffset)); 2455 __ movq(result, FieldOperand(string, String::kLengthOffset));
2316 } 2456 }
2317 2457
2318 2458
2319 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { 2459 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
2320 LOperand* input = instr->InputAt(0); 2460 LOperand* input = instr->InputAt(0);
2321 ASSERT(input->IsRegister() || input->IsStackSlot()); 2461 ASSERT(input->IsRegister() || input->IsStackSlot());
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
2660 // Pick the right runtime function to call. 2800 // Pick the right runtime function to call.
2661 if (instr->hydrogen()->depth() > 1) { 2801 if (instr->hydrogen()->depth() > 1) {
2662 CallRuntime(Runtime::kCreateObjectLiteral, 4, instr); 2802 CallRuntime(Runtime::kCreateObjectLiteral, 4, instr);
2663 } else { 2803 } else {
2664 CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr); 2804 CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr);
2665 } 2805 }
2666 } 2806 }
2667 2807
2668 2808
2669 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { 2809 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
2670 Abort("Unimplemented: %s", "DoRegExpLiteral"); 2810 NearLabel materialized;
2811 // Registers will be used as follows:
2812 // rdi = JS function.
2813 // rcx = literals array.
2814 // rbx = regexp literal.
2815 // rax = regexp literal clone.
2816 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
2817 __ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset));
2818 int literal_offset = FixedArray::kHeaderSize +
2819 instr->hydrogen()->literal_index() * kPointerSize;
2820 __ movq(rbx, FieldOperand(rcx, literal_offset));
2821 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
2822 __ j(not_equal, &materialized);
2823
2824 // Create regexp literal using runtime function
2825 // Result will be in eax.
Lasse Reichstein 2011/02/18 13:22:25 eax->rax
Mads Ager (chromium) 2011/02/18 13:58:47 Done.
2826 __ push(rcx);
2827 __ Push(Smi::FromInt(instr->hydrogen()->literal_index()));
2828 __ Push(instr->hydrogen()->pattern());
2829 __ Push(instr->hydrogen()->flags());
2830 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr);
2831 __ movq(rbx, rax);
2832
2833 __ bind(&materialized);
2834 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
2835 Label allocated, runtime_allocate;
2836 __ AllocateInNewSpace(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT);
2837 __ jmp(&allocated);
2838
2839 __ bind(&runtime_allocate);
2840 __ push(rbx);
2841 __ Push(Smi::FromInt(size));
2842 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
2843 __ pop(rbx);
2844
2845 __ bind(&allocated);
2846 // Copy the content into the newly allocated memory.
2847 // (Unroll copy loop once for better throughput).
2848 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
2849 __ movq(rdx, FieldOperand(rbx, i));
2850 __ movq(rcx, FieldOperand(rbx, i + kPointerSize));
2851 __ movq(FieldOperand(rax, i), rdx);
2852 __ movq(FieldOperand(rax, i + kPointerSize), rcx);
2853 }
2854 if ((size % (2 * kPointerSize)) != 0) {
2855 __ movq(rdx, FieldOperand(rbx, size - kPointerSize));
2856 __ movq(FieldOperand(rax, size - kPointerSize), rdx);
2857 }
2671 } 2858 }
2672 2859
2673 2860
2674 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { 2861 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
2675 // Use the fast case closure allocation code that allocates in new 2862 // Use the fast case closure allocation code that allocates in new
2676 // space for nested functions that don't need literals cloning. 2863 // space for nested functions that don't need literals cloning.
2677 Handle<SharedFunctionInfo> shared_info = instr->shared_info(); 2864 Handle<SharedFunctionInfo> shared_info = instr->shared_info();
2678 bool pretenure = instr->hydrogen()->pretenure(); 2865 bool pretenure = instr->hydrogen()->pretenure();
2679 if (shared_info->num_literals() == 0 && !pretenure) { 2866 if (shared_info->num_literals() == 0 && !pretenure) {
2680 FastNewClosureStub stub; 2867 FastNewClosureStub stub;
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
2869 RegisterEnvironmentForDeoptimization(environment); 3056 RegisterEnvironmentForDeoptimization(environment);
2870 ASSERT(osr_pc_offset_ == -1); 3057 ASSERT(osr_pc_offset_ == -1);
2871 osr_pc_offset_ = masm()->pc_offset(); 3058 osr_pc_offset_ = masm()->pc_offset();
2872 } 3059 }
2873 3060
2874 #undef __ 3061 #undef __
2875 3062
2876 } } // namespace v8::internal 3063 } } // namespace v8::internal
2877 3064
2878 #endif // V8_TARGET_ARCH_X64 3065 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/lithium-codegen-x64.h ('k') | src/x64/lithium-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698