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

Side by Side Diff: src/ia32/safe-codegen-ia32.cc

Issue 660077: NOT FOR COMMITTING: Add fast side-effect free floating point expressions. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 9 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/ia32/safe-codegen-ia32.h ('k') | src/v8-counters.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #include "v8.h"
29
30 #include "codegen-inl.h"
31 #include "compiler.h"
32 #include "debug.h"
33 #include "ast.h"
34 #include "virtual-frame-inl.h"
35 #include "safe-codegen-ia32.h"
36 #include "parser.h"
37 #include "macro-assembler-ia32.h"
38
39 namespace v8 {
40 namespace internal {
41
42 #define __ ACCESS_MASM(masm_)
43
44
45 // SafeSyntaxChecker - An AST Visitor that bails out and returns false
46 // for any unsupported AST nodes in a side-effect free expression.
47
48 #define BAILOUT(reason) \
49 do { \
50 if (FLAG_trace_bailout) { \
51 PrintF("%s\n", reason); \
52 } \
53 has_supported_syntax_ = false; \
54 return; \
55 } while (false)
56
57
58 #define CHECK_BAILOUT \
59 do { \
60 if (!has_supported_syntax_) return; \
61 } while (false)
62
63
64 #define DEFINE_STMT_VISIT(type) \
65 void SafeSyntaxChecker::Visit##type(type* stmt) { \
66 UNREACHABLE(); \
67 } \
68 \
69 void SafeGenerator::Visit##type(type* stmt) { \
70 UNREACHABLE(); \
71 }
72
73 STATEMENT_NODE_LIST(DEFINE_STMT_VISIT)
74
75 DEFINE_STMT_VISIT(Declaration)
76
77 #undef DEFINE_STMT_VISIT
78
79 void SafeSyntaxChecker::VisitFunctionLiteral(FunctionLiteral* expr) {
80 BAILOUT("FunctionLiteral");
81 }
82
83
84 void SafeSyntaxChecker::VisitFunctionBoilerplateLiteral(
85 FunctionBoilerplateLiteral* expr) {
86 BAILOUT("FunctionBoilerplateLiteral");
87 }
88
89
90 void SafeSyntaxChecker::VisitConditional(Conditional* expr) {
91 BAILOUT("Conditional");
92 }
93
94
95 void SafeSyntaxChecker::VisitSlot(Slot* expr) {
96 // Load variables directly from local or parameter slots.
97 // The arguments slot could be the hole, if lazy arguments are used,
98 // and is probably not a smi or heap number in any case.
99 if ((expr->type() == Slot::LOCAL && !expr->is_arguments()) ||
100 expr->type() == Slot::PARAMETER) {
101 ++xmm_stack_height_;
102 if (xmm_stack_height_ > MAX_XMM_STACK_HEIGHT) {
103 BAILOUT("Expression stack overflow");
104 }
105 } else {
106 BAILOUT("Slot is not local or parameter slot.");
107 }
108 }
109
110
111 void SafeSyntaxChecker::VisitVariableProxy(VariableProxy* expr) {
112 Variable* var = expr->AsVariable();
113 if (var != NULL && var->slot() != NULL) {
114 Visit(var->slot());
115 } else if (var != NULL && var->is_global() && !var->is_this()) {
116 BAILOUT("Global variable");
117 // Global variables are supported. Do nothing.
118 } else {
119 BAILOUT("VariableProxy has non-slot variable");
120 }
121 }
122
123
124 void SafeSyntaxChecker::VisitLiteral(Literal* expr) {
125 // Check that literal is a number.
126 if (expr->handle()->IsSmi() || expr->handle()->IsHeapNumber()) {
127 ++xmm_stack_height_;
128 if (xmm_stack_height_ > MAX_XMM_STACK_HEIGHT) {
129 BAILOUT("XMM stack height too great");
130 }
131 if (expr->handle()->IsHeapNumber()) {
132 has_constant_float_ = true;
133 }
134 } else {
135 BAILOUT("Non-number literal");
136 }
137 }
138
139
140 void SafeSyntaxChecker::VisitRegExpLiteral(RegExpLiteral* expr) {
141 BAILOUT("RegExpLiteral");
142 }
143
144
145 void SafeSyntaxChecker::VisitObjectLiteral(ObjectLiteral* expr) {
146 BAILOUT("ObjectLiteral");
147 }
148
149
150 void SafeSyntaxChecker::VisitArrayLiteral(ArrayLiteral* expr) {
151 BAILOUT("ArrayLiteral");
152 }
153
154
155 void SafeSyntaxChecker::VisitCatchExtensionObject(
156 CatchExtensionObject* expr) {
157 BAILOUT("CatchExtensionObject");
158 }
159
160
161 void SafeSyntaxChecker::VisitAssignment(Assignment* expr) {
162 BAILOUT("Assignment has a side effect");
163 }
164
165
166 void SafeSyntaxChecker::VisitThrow(Throw* expr) {
167 BAILOUT("Throw");
168 }
169
170
171 void SafeSyntaxChecker::VisitProperty(Property* expr) {
172 BAILOUT("Property");
173 }
174
175
176 void SafeSyntaxChecker::VisitCall(Call* expr) {
177 BAILOUT("Call");
178 }
179
180
181 void SafeSyntaxChecker::VisitCallNew(CallNew* expr) {
182 BAILOUT("CallNew");
183 }
184
185
186 void SafeSyntaxChecker::VisitCallRuntime(CallRuntime* expr) {
187 BAILOUT("CallRuntime");
188 }
189
190
191 void SafeSyntaxChecker::VisitUnaryOperation(UnaryOperation* expr) {
192 switch (expr->op()) {
193 case Token::ADD:
194 Visit(expr->expression());
195 break;
196 case Token::SUB:
197 Visit(expr->expression());
198 CHECK_BAILOUT;
199 if (xmm_stack_height_ == MAX_XMM_STACK_HEIGHT) {
200 // Need one extra register for doing the computation.
201 BAILOUT("XMM stack height too great");
202 }
203 ++num_operations_;
204 break;
205 case Token::DELETE:
206 case Token::TYPEOF:
207 case Token::VOID:
208 case Token::BIT_NOT:
209 case Token::NOT:
210 BAILOUT("Unsupported Unary Operation");
211 break;
212 default:
213 UNREACHABLE();
214 }
215 }
216
217
218 void SafeSyntaxChecker::VisitCountOperation(CountOperation* expr) {
219 BAILOUT("CountOperation");
220 }
221
222
223 void SafeSyntaxChecker::VisitBinaryOperation(BinaryOperation* expr) {
224 switch (expr->op()) {
225 case Token::ADD:
226 case Token::SUB:
227 case Token::DIV:
228 case Token::MUL:
229 Visit(expr->left());
230 CHECK_BAILOUT;
231 Visit(expr->right());
232 CHECK_BAILOUT;
233 ++num_operations_;
234 --xmm_stack_height_;
235 break;
236 case Token::MOD:
237 case Token::BIT_OR:
238 case Token::BIT_AND:
239 case Token::BIT_XOR:
240 case Token::SHL:
241 case Token::SHR:
242 case Token::SAR:
243 case Token::COMMA:
244 case Token::OR:
245 case Token::AND:
246 BAILOUT("Unsupported Binary Operation");
247 break;
248 default:
249 UNREACHABLE();
250 }
251 }
252
253
254 void SafeSyntaxChecker::VisitCompareOperation(CompareOperation* expr) {
255 BAILOUT("CompareOperation");
256 }
257
258
259 void SafeSyntaxChecker::VisitThisFunction(ThisFunction* expr) {
260 BAILOUT("ThisFunction");
261 }
262
263
264 // Generate code for a side-effect free expression.
265 // whesse works above this line
266 // --------------------------------------------------
267 // lrn works below this line
268
269 Result SafeGenerator::Generate(Expression* expr) {
270 JumpTarget allocation_succeeded;
271 Label allocation_failed;
272 ASSERT(CpuFeatures::IsSupported(SSE2));
273 CpuFeatures::Scope fscope(SSE2);
274
275 VirtualFrame* clone = new VirtualFrame(cgen_->frame());
276 __ AllocateHeapNumber(final_result_->reg(), scratch_->reg(),
277 no_reg, &allocation_failed);
278 cgen_->frame()->Push(scratch_);
279 allocation_succeeded.Jump(final_result_);
280 RegisterFile empty_regs;
281 cgen_->SetFrame(clone, &empty_regs);
282 __ bind(&allocation_failed);
283 unsafe_target_->Jump();
284
285 allocation_succeeded.Bind(final_result_);
286 *scratch_ = cgen_->frame()->Pop();
287 Visit(expr);
288 StoreXMM(final_result_->reg());
289 Result return_value = *final_result_;
290 final_result_->Unuse();
291 scratch_->Unuse();
292 return return_value;
293 }
294
295 void SafeGenerator::PushXMM(Handle<HeapNumber> literal) {
296 XMMRegister reg = AllocateStackElement();
297 __ mov(scratch_->reg(), Immediate(literal));
298 __ movdbl(reg, FieldOperand(scratch_->reg(), HeapNumber::kValueOffset));
299 }
300
301
302 void SafeGenerator::PushXMM(Handle<Smi> literal) {
303 XMMRegister reg = AllocateStackElement();
304 __ mov(scratch_->reg(), Immediate(literal->value()));
305 __ cvtsi2sd(reg, Operand(scratch_->reg()));
306 }
307
308
309 void SafeGenerator::PushXMM(Slot* slot) {
310 Register scratch = scratch_->reg();
311 ASSERT((slot->type() == Slot::LOCAL && !slot->is_arguments()) ||
312 slot->type() == Slot::PARAMETER);
313 if (slot->type() == Slot::PARAMETER) {
314 cgen_->frame()->PushParameterAt(slot->index());
315 } else { // slot->type == Slot::LOCAL
316 cgen_->frame()->PushLocalAt(slot->index());
317 }
318 Result value = cgen_->frame()->Pop();
319 XMMRegister reg = AllocateStackElement();
320
321 if (value.is_register()) {
322 // Convert to double.
323 __ test(Operand(value.reg()), Immediate(kSmiTagMask));
324 Label is_smi;
325 Label done;
326 __ j(zero, &is_smi);
327 // This test fails on non-numbers, including the hole representing
328 // an uninitialized constant.
329 __ cmp(FieldOperand(value.reg(), HeapObject::kMapOffset),
330 Immediate(Factory::heap_number_map()));
331 unsafe_target_->Branch(not_equal);
332 __ movdbl(reg, FieldOperand(value.reg(), HeapNumber::kValueOffset));
333 __ jmp(&done);
334
335 __ bind(&is_smi);
336 // Should we spill the existing register, and untag it, or should
337 // we copy to the scratch register?
338 __ mov(scratch, value.reg());
339 __ SmiUntag(scratch);
340 __ cvtsi2sd(reg, Operand(scratch));
341
342 __ bind(&done);
343 } else {
344 ASSERT(value.is_constant());
345 if (value.handle()->IsHeapNumber()) {
346 __ mov(scratch, value.handle());
347 __ movdbl(reg, FieldOperand(scratch, HeapNumber::kValueOffset));
348 } else {
349 ASSERT(value.handle()->IsSmi());
350 __ mov(scratch, Immediate(Smi::cast(*value.handle())->value()));
351 __ cvtsi2sd(reg, Operand(scratch));
352 }
353 }
354 }
355
356
357 void SafeGenerator::StoreXMM(Register heapNumber) {
358 ASSERT(xmm_stack_height_ > 0);
359 XMMRegister reg = XMMStackElement(0);
360 __ movdbl(FieldOperand(heapNumber, HeapNumber::kValueOffset), reg);
361 FreeStackTop();
362 }
363
364
365 // Utility functions.
366 XMMRegister SafeGenerator::XMMStackElement(int offset_from_top) {
367 ASSERT(offset_from_top < xmm_stack_height_);
368 ASSERT(offset_from_top < kNumXMMRegisters); // The rest have been spilled!
369 int reg_code = (xmm_stack_height_ - offset_from_top - 1);
370 XMMRegister reg = { reg_code };
371 ASSERT(reg.is_valid());
372 return reg;
373 }
374
375
376 void SafeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
377 UNREACHABLE();
378 }
379
380
381 void SafeGenerator::VisitFunctionBoilerplateLiteral(
382 FunctionBoilerplateLiteral* expr) {
383 UNREACHABLE();
384 }
385
386
387 void SafeGenerator::VisitConditional(Conditional* expr) {
388 UNREACHABLE();
389 }
390
391
392 void SafeGenerator::VisitSlot(Slot* expr) {
393 // Check that slot is local or context.
394 if ((expr->type() == Slot::LOCAL && !expr->is_arguments()) ||
395 expr->type() == Slot::PARAMETER) {
396 PushXMM(expr);
397 } else {
398 UNREACHABLE();
399 }
400 }
401
402
403 void SafeGenerator::VisitVariableProxy(VariableProxy* expr) {
404 Variable* var = expr->AsVariable();
405 if (var != NULL && var->slot() != NULL) {
406 Visit(var->slot());
407 } else {
408 UNREACHABLE();
409 }
410 }
411
412
413 void SafeGenerator::VisitLiteral(Literal* expr) {
414 // Check that literal is a number.
415 if (expr->handle()->IsSmi()) {
416 PushXMM(Handle<Smi>::cast(expr->handle()));
417 } else if (expr->handle()->IsHeapNumber()) {
418 PushXMM(Handle<HeapNumber>::cast(expr->handle()));
419 } else {
420 UNREACHABLE();
421 }
422 }
423
424
425 void SafeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
426 UNREACHABLE();
427 }
428
429
430 void SafeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
431 UNREACHABLE();
432 }
433
434
435 void SafeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
436 UNREACHABLE();
437 }
438
439
440 void SafeGenerator::VisitCatchExtensionObject(
441 CatchExtensionObject* expr) {
442 UNREACHABLE();
443 }
444
445
446 void SafeGenerator::VisitAssignment(Assignment* expr) {
447 UNREACHABLE();
448 }
449
450
451 void SafeGenerator::VisitThrow(Throw* expr) {
452 UNREACHABLE();
453 }
454
455
456 void SafeGenerator::VisitProperty(Property* expr) {
457 UNREACHABLE();
458 }
459
460
461 void SafeGenerator::VisitCall(Call* expr) {
462 UNREACHABLE();
463 }
464
465
466 void SafeGenerator::VisitCallNew(CallNew* expr) {
467 UNREACHABLE();
468 }
469
470
471 void SafeGenerator::VisitCallRuntime(CallRuntime* expr) {
472 UNREACHABLE();
473 }
474
475
476 void SafeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
477 switch (expr->op()) {
478 case Token::ADD:
479 Visit(expr->expression());
480 break;
481 case Token::SUB: {
482 Visit(expr->expression());
483 XMMRegister arg = XMMStackElement(0);
484 XMMRegister tmp = AllocateStackElement();
485 // Load bit pattern 0x8000000000000000 to new XMM register,
486 // and PXOR it with the result of expr to negate that.
487 __ mov(Operand(scratch_->reg()), Immediate(0x80000000)); // -0 as float.
488 __ movd(tmp, Operand(scratch_->reg()));
489 __ cvtss2sd(tmp, tmp);
490 __ pxor(arg, tmp);
491 FreeStackTop();
492 break;
493 }
494 case Token::DELETE:
495 case Token::TYPEOF:
496 case Token::VOID:
497 case Token::BIT_NOT:
498 case Token::NOT:
499 UNREACHABLE();
500 break;
501 default:
502 UNREACHABLE();
503 }
504 }
505
506
507 void SafeGenerator::VisitCountOperation(CountOperation* expr) {
508 UNREACHABLE();
509 }
510
511
512 void SafeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
513 Comment cmnt(masm_, "[ BinaryOperation");
514 Visit(expr->left());
515 Visit(expr->right());
516 ASSERT(xmm_stack_height_ >= 2);
517 switch (expr->op()) {
518 case Token::ADD:
519 __ addsd(XMMStackElement(1), XMMStackElement(0));
520 break;
521 case Token::SUB:
522 __ subsd(XMMStackElement(1), XMMStackElement(0));
523 break;
524 case Token::DIV:
525 __ divsd(XMMStackElement(1), XMMStackElement(0));
526 break;
527 case Token::MUL:
528 __ mulsd(XMMStackElement(1), XMMStackElement(0));
529 break;
530 case Token::MOD:
531 case Token::BIT_OR:
532 case Token::BIT_AND:
533 case Token::BIT_XOR:
534 case Token::SHL:
535 case Token::SHR:
536 case Token::SAR:
537 case Token::COMMA:
538 case Token::OR:
539 case Token::AND:
540 default:
541 UNREACHABLE();
542 }
543 FreeStackTop();
544 }
545
546
547 void SafeGenerator::VisitCompareOperation(CompareOperation* expr) {
548 UNREACHABLE();
549 }
550
551
552 void SafeGenerator::VisitThisFunction(ThisFunction* expr) {
553 UNREACHABLE();
554 }
555 #undef __
556
557 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/safe-codegen-ia32.h ('k') | src/v8-counters.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698