| 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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 | 44 |
| 45 | 45 |
| 46 void FastCodeGenerator::EmitLoadReceiver() { | 46 void FastCodeGenerator::EmitLoadReceiver() { |
| 47 // Offset 2 is due to return address and saved frame pointer. | 47 // Offset 2 is due to return address and saved frame pointer. |
| 48 int index = 2 + function()->scope()->num_parameters(); | 48 int index = 2 + function()->scope()->num_parameters(); |
| 49 __ mov(receiver_reg(), Operand(ebp, index * kPointerSize)); | 49 __ mov(receiver_reg(), Operand(ebp, index * kPointerSize)); |
| 50 } | 50 } |
| 51 | 51 |
| 52 | 52 |
| 53 void FastCodeGenerator::EmitGlobalVariableLoad(Handle<Object> cell) { | 53 void FastCodeGenerator::EmitGlobalVariableLoad(Handle<Object> cell) { |
| 54 ASSERT(!destination().is(no_reg)); |
| 54 ASSERT(cell->IsJSGlobalPropertyCell()); | 55 ASSERT(cell->IsJSGlobalPropertyCell()); |
| 55 __ mov(accumulator0(), Immediate(cell)); | 56 |
| 56 __ mov(accumulator0(), | 57 __ mov(destination(), Immediate(cell)); |
| 57 FieldOperand(accumulator0(), JSGlobalPropertyCell::kValueOffset)); | 58 __ mov(destination(), |
| 59 FieldOperand(destination(), JSGlobalPropertyCell::kValueOffset)); |
| 58 if (FLAG_debug_code) { | 60 if (FLAG_debug_code) { |
| 59 __ cmp(accumulator0(), Factory::the_hole_value()); | 61 __ cmp(destination(), Factory::the_hole_value()); |
| 60 __ Check(not_equal, "DontDelete cells can't contain the hole"); | 62 __ Check(not_equal, "DontDelete cells can't contain the hole"); |
| 61 } | 63 } |
| 62 } | 64 } |
| 63 | 65 |
| 64 | 66 |
| 65 void FastCodeGenerator::EmitThisPropertyStore(Handle<String> name) { | 67 void FastCodeGenerator::EmitThisPropertyStore(Handle<String> name) { |
| 66 LookupResult lookup; | 68 LookupResult lookup; |
| 67 info()->receiver()->Lookup(*name, &lookup); | 69 info()->receiver()->Lookup(*name, &lookup); |
| 68 | 70 |
| 69 ASSERT(lookup.holder() == *info()->receiver()); | 71 ASSERT(lookup.holder() == *info()->receiver()); |
| 70 ASSERT(lookup.type() == FIELD); | 72 ASSERT(lookup.type() == FIELD); |
| 71 Handle<Map> map(Handle<HeapObject>::cast(info()->receiver())->map()); | 73 Handle<Map> map(Handle<HeapObject>::cast(info()->receiver())->map()); |
| 72 int index = lookup.GetFieldIndex() - map->inobject_properties(); | 74 int index = lookup.GetFieldIndex() - map->inobject_properties(); |
| 73 int offset = index * kPointerSize; | 75 int offset = index * kPointerSize; |
| 74 | 76 |
| 75 // Negative offsets are inobject properties. | 77 // Negative offsets are inobject properties. |
| 76 if (offset < 0) { | 78 if (offset < 0) { |
| 77 offset += map->instance_size(); | 79 offset += map->instance_size(); |
| 78 __ mov(scratch0(), receiver_reg()); // Copy receiver for write barrier. | 80 __ mov(scratch0(), receiver_reg()); // Copy receiver for write barrier. |
| 79 } else { | 81 } else { |
| 80 offset += FixedArray::kHeaderSize; | 82 offset += FixedArray::kHeaderSize; |
| 81 __ mov(scratch0(), | 83 __ mov(scratch0(), |
| 82 FieldOperand(receiver_reg(), JSObject::kPropertiesOffset)); | 84 FieldOperand(receiver_reg(), JSObject::kPropertiesOffset)); |
| 83 } | 85 } |
| 84 // Perform the store. | 86 // Perform the store. |
| 85 __ mov(FieldOperand(scratch0(), offset), accumulator0()); | 87 __ mov(FieldOperand(scratch0(), offset), accumulator0()); |
| 86 // Preserve value from write barrier in case it's needed. | 88 if (destination().is(no_reg)) { |
| 87 __ mov(accumulator1(), accumulator0()); | 89 __ RecordWrite(scratch0(), offset, accumulator0(), scratch1()); |
| 88 // The other accumulator register is available as a scratch register | 90 } else { |
| 89 // because this is not an AST leaf node. | 91 // Copy the value to the other accumulator to preserve a copy from the |
| 90 __ RecordWrite(scratch0(), offset, accumulator1(), scratch1()); | 92 // write barrier. One of the accumulators is available as a scratch |
| 93 // register. |
| 94 __ mov(accumulator1(), accumulator0()); |
| 95 Register value_scratch = other_accumulator(destination()); |
| 96 __ RecordWrite(scratch0(), offset, value_scratch, scratch1()); |
| 97 } |
| 91 } | 98 } |
| 92 | 99 |
| 93 | 100 |
| 101 void FastCodeGenerator::EmitThisPropertyLoad(Handle<String> name) { |
| 102 ASSERT(!destination().is(no_reg)); |
| 103 LookupResult lookup; |
| 104 info()->receiver()->Lookup(*name, &lookup); |
| 105 |
| 106 ASSERT(lookup.holder() == *info()->receiver()); |
| 107 ASSERT(lookup.type() == FIELD); |
| 108 Handle<Map> map(Handle<HeapObject>::cast(info()->receiver())->map()); |
| 109 int index = lookup.GetFieldIndex() - map->inobject_properties(); |
| 110 int offset = index * kPointerSize; |
| 111 |
| 112 // Perform the load. Negative offsets are inobject properties. |
| 113 if (offset < 0) { |
| 114 offset += map->instance_size(); |
| 115 __ mov(destination(), FieldOperand(receiver_reg(), offset)); |
| 116 } else { |
| 117 offset += FixedArray::kHeaderSize; |
| 118 __ mov(scratch0(), |
| 119 FieldOperand(receiver_reg(), JSObject::kPropertiesOffset)); |
| 120 __ mov(destination(), FieldOperand(scratch0(), offset)); |
| 121 } |
| 122 } |
| 123 |
| 124 |
| 125 void FastCodeGenerator::EmitBitOr() { |
| 126 Register copied; // One operand is copied to a scratch register. |
| 127 Register other; // The other is not modified by the operation. |
| 128 Register check; // A register is used for the smi check/operation. |
| 129 if (destination().is(no_reg)) { |
| 130 copied = accumulator1(); // Arbitrary choice of operand to copy. |
| 131 other = accumulator0(); |
| 132 check = scratch0(); // Do not clobber either operand register. |
| 133 } else { |
| 134 copied = destination(); |
| 135 other = other_accumulator(destination()); |
| 136 check = destination(); |
| 137 } |
| 138 __ mov(scratch0(), copied); |
| 139 __ or_(check, Operand(other)); |
| 140 __ test(check, Immediate(kSmiTagMask)); |
| 141 |
| 142 // Restore the clobbered operand if necessary. |
| 143 if (destination().is(no_reg)) { |
| 144 __ j(not_zero, bailout(), not_taken); |
| 145 } else { |
| 146 Label done; |
| 147 __ j(zero, &done, taken); |
| 148 __ mov(copied, scratch0()); |
| 149 __ jmp(bailout()); |
| 150 __ bind(&done); |
| 151 } |
| 152 } |
| 153 |
| 154 |
| 94 void FastCodeGenerator::Generate(CompilationInfo* compilation_info) { | 155 void FastCodeGenerator::Generate(CompilationInfo* compilation_info) { |
| 95 ASSERT(info_ == NULL); | 156 ASSERT(info_ == NULL); |
| 96 info_ = compilation_info; | 157 info_ = compilation_info; |
| 97 | 158 |
| 98 // Save the caller's frame pointer and set up our own. | 159 // Save the caller's frame pointer and set up our own. |
| 99 Comment prologue_cmnt(masm(), ";; Prologue"); | 160 Comment prologue_cmnt(masm(), ";; Prologue"); |
| 100 __ push(ebp); | 161 __ push(ebp); |
| 101 __ mov(ebp, esp); | 162 __ mov(ebp, esp); |
| 102 __ push(esi); // Context. | 163 __ push(esi); // Context. |
| 103 __ push(edi); // Closure. | 164 __ push(edi); // Closure. |
| 104 // Note that we keep a live register reference to esi (context) at this | 165 // Note that we keep a live register reference to esi (context) at this |
| 105 // point. | 166 // point. |
| 106 | 167 |
| 107 // Receiver (this) is allocated to a fixed register. | 168 // Receiver (this) is allocated to a fixed register. |
| 108 if (info()->has_this_properties()) { | 169 if (info()->has_this_properties()) { |
| 109 Comment cmnt(masm(), ";; MapCheck(this)"); | 170 Comment cmnt(masm(), ";; MapCheck(this)"); |
| 110 if (FLAG_print_ir) { | 171 if (FLAG_print_ir) { |
| 111 PrintF("MapCheck(this)\n"); | 172 PrintF("#: MapCheck(this)\n"); |
| 112 } | 173 } |
| 113 ASSERT(info()->has_receiver() && info()->receiver()->IsHeapObject()); | 174 ASSERT(info()->has_receiver() && info()->receiver()->IsHeapObject()); |
| 114 Handle<HeapObject> object = Handle<HeapObject>::cast(info()->receiver()); | 175 Handle<HeapObject> object = Handle<HeapObject>::cast(info()->receiver()); |
| 115 Handle<Map> map(object->map()); | 176 Handle<Map> map(object->map()); |
| 116 EmitLoadReceiver(); | 177 EmitLoadReceiver(); |
| 117 __ CheckMap(receiver_reg(), map, bailout(), false); | 178 __ CheckMap(receiver_reg(), map, bailout(), false); |
| 118 } | 179 } |
| 119 | 180 |
| 120 // If there is a global variable access check if the global object is the | 181 // If there is a global variable access check if the global object is the |
| 121 // same as at lazy-compilation time. | 182 // same as at lazy-compilation time. |
| 122 if (info()->has_globals()) { | 183 if (info()->has_globals()) { |
| 123 Comment cmnt(masm(), ";; MapCheck(GLOBAL)"); | 184 Comment cmnt(masm(), ";; MapCheck(GLOBAL)"); |
| 124 if (FLAG_print_ir) { | 185 if (FLAG_print_ir) { |
| 125 PrintF("MapCheck(GLOBAL)\n"); | 186 PrintF("#: MapCheck(GLOBAL)\n"); |
| 126 } | 187 } |
| 127 ASSERT(info()->has_global_object()); | 188 ASSERT(info()->has_global_object()); |
| 128 Handle<Map> map(info()->global_object()->map()); | 189 Handle<Map> map(info()->global_object()->map()); |
| 129 __ mov(scratch0(), CodeGenerator::GlobalObject()); | 190 __ mov(scratch0(), CodeGenerator::GlobalObject()); |
| 130 __ CheckMap(scratch0(), map, bailout(), true); | 191 __ CheckMap(scratch0(), map, bailout(), true); |
| 131 } | 192 } |
| 132 | 193 |
| 133 VisitStatements(function()->body()); | 194 VisitStatements(function()->body()); |
| 134 | 195 |
| 135 Comment return_cmnt(masm(), ";; Return(<undefined>)"); | 196 Comment return_cmnt(masm(), ";; Return(<undefined>)"); |
| 136 if (FLAG_print_ir) { | 197 if (FLAG_print_ir) { |
| 137 PrintF("Return(<undefined>)\n"); | 198 PrintF("#: Return(<undefined>)\n"); |
| 138 } | 199 } |
| 139 __ mov(eax, Factory::undefined_value()); | 200 __ mov(eax, Factory::undefined_value()); |
| 140 __ mov(esp, ebp); | 201 __ mov(esp, ebp); |
| 141 __ pop(ebp); | 202 __ pop(ebp); |
| 142 __ ret((scope()->num_parameters() + 1) * kPointerSize); | 203 __ ret((scope()->num_parameters() + 1) * kPointerSize); |
| 143 | 204 |
| 144 __ bind(&bailout_); | 205 __ bind(&bailout_); |
| 145 } | 206 } |
| 146 | 207 |
| 147 | 208 |
| 148 #undef __ | 209 #undef __ |
| 149 | 210 |
| 150 | 211 |
| 151 } } // namespace v8::internal | 212 } } // namespace v8::internal |
| OLD | NEW |