OLD | NEW |
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 17 matching lines...) Expand all Loading... |
28 #include "v8.h" | 28 #include "v8.h" |
29 | 29 |
30 #include "codegen-inl.h" | 30 #include "codegen-inl.h" |
31 #include "fast-codegen.h" | 31 #include "fast-codegen.h" |
32 | 32 |
33 namespace v8 { | 33 namespace v8 { |
34 namespace internal { | 34 namespace internal { |
35 | 35 |
36 #define __ ACCESS_MASM(masm()) | 36 #define __ ACCESS_MASM(masm()) |
37 | 37 |
38 // Registers rcx, rdi, and r8-r15 are free to use as scratch registers | |
39 // without saving and restoring any other registers. | |
40 Register FastCodeGenerator::accumulator0() { return rax; } | 38 Register FastCodeGenerator::accumulator0() { return rax; } |
41 Register FastCodeGenerator::accumulator1() { return rdx; } | 39 Register FastCodeGenerator::accumulator1() { return rdx; } |
42 Register FastCodeGenerator::scratch0() { return rcx; } | 40 Register FastCodeGenerator::scratch0() { return rcx; } |
43 Register FastCodeGenerator::scratch1() { return rdi; } | 41 Register FastCodeGenerator::scratch1() { return rdi; } |
44 Register FastCodeGenerator::receiver_reg() { return rbx; } | 42 Register FastCodeGenerator::receiver_reg() { return rbx; } |
45 Register FastCodeGenerator::context_reg() { return rsi; } | 43 Register FastCodeGenerator::context_reg() { return rsi; } |
46 | 44 |
47 | 45 |
48 void FastCodeGenerator::EmitLoadReceiver() { | 46 void FastCodeGenerator::EmitLoadReceiver() { |
49 // Offset 2 is due to return address and saved frame pointer. | 47 // Offset 2 is due to return address and saved frame pointer. |
50 int index = 2 + scope()->num_parameters(); | 48 int index = 2 + scope()->num_parameters(); |
51 __ movq(receiver_reg(), Operand(rbp, index * kPointerSize)); | 49 __ movq(receiver_reg(), Operand(rbp, index * kPointerSize)); |
52 } | 50 } |
53 | 51 |
54 | 52 |
55 void FastCodeGenerator::EmitGlobalVariableLoad(Handle<Object> cell) { | 53 void FastCodeGenerator::EmitGlobalVariableLoad(Handle<Object> cell) { |
| 54 ASSERT(!destination().is(no_reg)); |
56 ASSERT(cell->IsJSGlobalPropertyCell()); | 55 ASSERT(cell->IsJSGlobalPropertyCell()); |
57 __ Move(accumulator0(), cell); | 56 __ Move(destination(), cell); |
58 __ movq(accumulator0(), | 57 __ movq(destination(), |
59 FieldOperand(accumulator0(), JSGlobalPropertyCell::kValueOffset)); | 58 FieldOperand(destination(), JSGlobalPropertyCell::kValueOffset)); |
60 if (FLAG_debug_code) { | 59 if (FLAG_debug_code) { |
61 __ Cmp(accumulator0(), Factory::the_hole_value()); | 60 __ Cmp(destination(), Factory::the_hole_value()); |
62 __ Check(not_equal, "DontDelete cells can't contain the hole"); | 61 __ Check(not_equal, "DontDelete cells can't contain the hole"); |
63 } | 62 } |
64 } | 63 } |
65 | 64 |
66 | 65 |
67 void FastCodeGenerator::EmitThisPropertyStore(Handle<String> name) { | 66 void FastCodeGenerator::EmitThisPropertyStore(Handle<String> name) { |
68 LookupResult lookup; | 67 LookupResult lookup; |
69 info()->receiver()->Lookup(*name, &lookup); | 68 info()->receiver()->Lookup(*name, &lookup); |
70 | 69 |
71 ASSERT(lookup.holder() == *info()->receiver()); | 70 ASSERT(lookup.holder() == *info()->receiver()); |
72 ASSERT(lookup.type() == FIELD); | 71 ASSERT(lookup.type() == FIELD); |
73 Handle<Map> map(Handle<HeapObject>::cast(info()->receiver())->map()); | 72 Handle<Map> map(Handle<HeapObject>::cast(info()->receiver())->map()); |
74 int index = lookup.GetFieldIndex() - map->inobject_properties(); | 73 int index = lookup.GetFieldIndex() - map->inobject_properties(); |
75 int offset = index * kPointerSize; | 74 int offset = index * kPointerSize; |
76 | 75 |
77 // Negative offsets are inobject properties. | 76 // Negative offsets are inobject properties. |
78 if (offset < 0) { | 77 if (offset < 0) { |
79 offset += map->instance_size(); | 78 offset += map->instance_size(); |
80 __ movq(scratch0(), receiver_reg()); // Copy receiver for write barrier. | 79 __ movq(scratch0(), receiver_reg()); // Copy receiver for write barrier. |
81 } else { | 80 } else { |
82 offset += FixedArray::kHeaderSize; | 81 offset += FixedArray::kHeaderSize; |
83 __ movq(scratch0(), | 82 __ movq(scratch0(), |
84 FieldOperand(receiver_reg(), JSObject::kPropertiesOffset)); | 83 FieldOperand(receiver_reg(), JSObject::kPropertiesOffset)); |
85 } | 84 } |
86 // Perform the store. | 85 // Perform the store. |
87 __ movq(FieldOperand(scratch0(), offset), accumulator0()); | 86 __ movq(FieldOperand(scratch0(), offset), accumulator0()); |
88 // Preserve value from write barrier in case it's needed. | 87 if (destination().is(no_reg)) { |
89 __ movq(accumulator1(), accumulator0()); | 88 __ RecordWrite(scratch0(), offset, accumulator0(), scratch1()); |
90 // The other accumulator register is available as a scratch register | 89 } else { |
91 // because this is not an AST leaf node. | 90 // Copy the value to the other accumulator to preserve a copy from the |
92 __ RecordWrite(scratch0(), offset, accumulator1(), scratch1()); | 91 // write barrier. One of the accumulators is available as a scratch |
| 92 // register. |
| 93 __ movq(accumulator1(), accumulator0()); |
| 94 Register value_scratch = other_accumulator(destination()); |
| 95 __ RecordWrite(scratch0(), offset, value_scratch, scratch1()); |
| 96 } |
93 } | 97 } |
94 | 98 |
95 | 99 |
| 100 void FastCodeGenerator::EmitThisPropertyLoad(Handle<String> name) { |
| 101 ASSERT(!destination().is(no_reg)); |
| 102 LookupResult lookup; |
| 103 info()->receiver()->Lookup(*name, &lookup); |
| 104 |
| 105 ASSERT(lookup.holder() == *info()->receiver()); |
| 106 ASSERT(lookup.type() == FIELD); |
| 107 Handle<Map> map(Handle<HeapObject>::cast(info()->receiver())->map()); |
| 108 int index = lookup.GetFieldIndex() - map->inobject_properties(); |
| 109 int offset = index * kPointerSize; |
| 110 |
| 111 // Perform the load. Negative offsets are inobject properties. |
| 112 if (offset < 0) { |
| 113 offset += map->instance_size(); |
| 114 __ movq(destination(), FieldOperand(receiver_reg(), offset)); |
| 115 } else { |
| 116 offset += FixedArray::kHeaderSize; |
| 117 __ movq(scratch0(), |
| 118 FieldOperand(receiver_reg(), JSObject::kPropertiesOffset)); |
| 119 __ movq(destination(), FieldOperand(scratch0(), offset)); |
| 120 } |
| 121 } |
| 122 |
| 123 |
| 124 void FastCodeGenerator::EmitBitOr() { |
| 125 Register copied; // One operand is copied to a scratch register. |
| 126 Register other; // The other is not modified by the operation. |
| 127 Register check; // A register is used for the smi check/operation. |
| 128 if (destination().is(no_reg)) { |
| 129 copied = accumulator1(); // Arbitrary choice of operand to copy. |
| 130 other = accumulator0(); |
| 131 check = scratch0(); // Do not clobber either operand register. |
| 132 } else { |
| 133 copied = destination(); |
| 134 other = other_accumulator(destination()); |
| 135 check = destination(); |
| 136 } |
| 137 __ movq(scratch0(), copied); |
| 138 __ or_(check, other); |
| 139 // Restore the clobbered operand if necessary. |
| 140 if (destination().is(no_reg)) { |
| 141 __ JumpIfNotSmi(check, bailout()); |
| 142 } else { |
| 143 Label done; |
| 144 __ JumpIfSmi(check, &done); |
| 145 __ movq(copied, scratch0()); |
| 146 __ jmp(bailout()); |
| 147 __ bind(&done); |
| 148 } |
| 149 } |
| 150 |
| 151 |
96 void FastCodeGenerator::Generate(CompilationInfo* compilation_info) { | 152 void FastCodeGenerator::Generate(CompilationInfo* compilation_info) { |
97 ASSERT(info_ == NULL); | 153 ASSERT(info_ == NULL); |
98 info_ = compilation_info; | 154 info_ = compilation_info; |
99 | 155 |
100 // Save the caller's frame pointer and set up our own. | 156 // Save the caller's frame pointer and set up our own. |
101 Comment prologue_cmnt(masm(), ";; Prologue"); | 157 Comment prologue_cmnt(masm(), ";; Prologue"); |
102 __ push(rbp); | 158 __ push(rbp); |
103 __ movq(rbp, rsp); | 159 __ movq(rbp, rsp); |
104 __ push(rsi); // Context. | 160 __ push(rsi); // Context. |
105 __ push(rdi); // Closure. | 161 __ push(rdi); // Closure. |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 __ ret((scope()->num_parameters() + 1) * kPointerSize); | 200 __ ret((scope()->num_parameters() + 1) * kPointerSize); |
145 | 201 |
146 __ bind(&bailout_); | 202 __ bind(&bailout_); |
147 } | 203 } |
148 | 204 |
149 | 205 |
150 #undef __ | 206 #undef __ |
151 | 207 |
152 | 208 |
153 } } // namespace v8::internal | 209 } } // namespace v8::internal |
OLD | NEW |