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/fast-codegen-ia32.cc

Issue 3152016: Remove experimental fast-codegen. We are no longer working on this (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 10 years, 4 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/fast-codegen-ia32.h ('k') | src/ia32/full-codegen-ia32.cc » ('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 #if defined(V8_TARGET_ARCH_IA32)
31
32 #include "codegen-inl.h"
33 #include "fast-codegen.h"
34 #include "data-flow.h"
35 #include "scopes.h"
36
37 namespace v8 {
38 namespace internal {
39
40 #define BAILOUT(reason) \
41 do { \
42 if (FLAG_trace_bailout) { \
43 PrintF("%s\n", reason); \
44 } \
45 has_supported_syntax_ = false; \
46 return; \
47 } while (false)
48
49
50 #define CHECK_BAILOUT \
51 do { \
52 if (!has_supported_syntax_) return; \
53 } while (false)
54
55
56 void FastCodeGenSyntaxChecker::Check(CompilationInfo* info) {
57 info_ = info;
58
59 // We do not specialize if we do not have a receiver or if it is not a
60 // JS object with fast mode properties.
61 if (!info->has_receiver()) BAILOUT("No receiver");
62 if (!info->receiver()->IsJSObject()) BAILOUT("Receiver is not an object");
63 Handle<JSObject> object = Handle<JSObject>::cast(info->receiver());
64 if (!object->HasFastProperties()) BAILOUT("Receiver is in dictionary mode");
65
66 // We do not support stack or heap slots (both of which require
67 // allocation).
68 Scope* scope = info->scope();
69 if (scope->num_stack_slots() > 0) {
70 BAILOUT("Function has stack-allocated locals");
71 }
72 if (scope->num_heap_slots() > 0) {
73 BAILOUT("Function has context-allocated locals");
74 }
75
76 VisitDeclarations(scope->declarations());
77 CHECK_BAILOUT;
78
79 // We do not support empty function bodies.
80 if (info->function()->body()->is_empty()) {
81 BAILOUT("Function has an empty body");
82 }
83 VisitStatements(info->function()->body());
84 }
85
86
87 void FastCodeGenSyntaxChecker::VisitDeclarations(
88 ZoneList<Declaration*>* decls) {
89 if (!decls->is_empty()) BAILOUT("Function has declarations");
90 }
91
92
93 void FastCodeGenSyntaxChecker::VisitStatements(ZoneList<Statement*>* stmts) {
94 if (stmts->length() != 1) {
95 BAILOUT("Function body is not a singleton statement.");
96 }
97 Visit(stmts->at(0));
98 }
99
100
101 void FastCodeGenSyntaxChecker::VisitDeclaration(Declaration* decl) {
102 UNREACHABLE();
103 }
104
105
106 void FastCodeGenSyntaxChecker::VisitBlock(Block* stmt) {
107 VisitStatements(stmt->statements());
108 }
109
110
111 void FastCodeGenSyntaxChecker::VisitExpressionStatement(
112 ExpressionStatement* stmt) {
113 Visit(stmt->expression());
114 }
115
116
117 void FastCodeGenSyntaxChecker::VisitEmptyStatement(EmptyStatement* stmt) {
118 // Supported.
119 }
120
121
122 void FastCodeGenSyntaxChecker::VisitIfStatement(IfStatement* stmt) {
123 BAILOUT("IfStatement");
124 }
125
126
127 void FastCodeGenSyntaxChecker::VisitContinueStatement(ContinueStatement* stmt) {
128 BAILOUT("Continuestatement");
129 }
130
131
132 void FastCodeGenSyntaxChecker::VisitBreakStatement(BreakStatement* stmt) {
133 BAILOUT("BreakStatement");
134 }
135
136
137 void FastCodeGenSyntaxChecker::VisitReturnStatement(ReturnStatement* stmt) {
138 BAILOUT("ReturnStatement");
139 }
140
141
142 void FastCodeGenSyntaxChecker::VisitWithEnterStatement(
143 WithEnterStatement* stmt) {
144 BAILOUT("WithEnterStatement");
145 }
146
147
148 void FastCodeGenSyntaxChecker::VisitWithExitStatement(WithExitStatement* stmt) {
149 BAILOUT("WithExitStatement");
150 }
151
152
153 void FastCodeGenSyntaxChecker::VisitSwitchStatement(SwitchStatement* stmt) {
154 BAILOUT("SwitchStatement");
155 }
156
157
158 void FastCodeGenSyntaxChecker::VisitDoWhileStatement(DoWhileStatement* stmt) {
159 BAILOUT("DoWhileStatement");
160 }
161
162
163 void FastCodeGenSyntaxChecker::VisitWhileStatement(WhileStatement* stmt) {
164 BAILOUT("WhileStatement");
165 }
166
167
168 void FastCodeGenSyntaxChecker::VisitForStatement(ForStatement* stmt) {
169 BAILOUT("ForStatement");
170 }
171
172
173 void FastCodeGenSyntaxChecker::VisitForInStatement(ForInStatement* stmt) {
174 BAILOUT("ForInStatement");
175 }
176
177
178 void FastCodeGenSyntaxChecker::VisitTryCatchStatement(TryCatchStatement* stmt) {
179 BAILOUT("TryCatchStatement");
180 }
181
182
183 void FastCodeGenSyntaxChecker::VisitTryFinallyStatement(
184 TryFinallyStatement* stmt) {
185 BAILOUT("TryFinallyStatement");
186 }
187
188
189 void FastCodeGenSyntaxChecker::VisitDebuggerStatement(
190 DebuggerStatement* stmt) {
191 BAILOUT("DebuggerStatement");
192 }
193
194
195 void FastCodeGenSyntaxChecker::VisitFunctionLiteral(FunctionLiteral* expr) {
196 BAILOUT("FunctionLiteral");
197 }
198
199
200 void FastCodeGenSyntaxChecker::VisitSharedFunctionInfoLiteral(
201 SharedFunctionInfoLiteral* expr) {
202 BAILOUT("SharedFunctionInfoLiteral");
203 }
204
205
206 void FastCodeGenSyntaxChecker::VisitConditional(Conditional* expr) {
207 BAILOUT("Conditional");
208 }
209
210
211 void FastCodeGenSyntaxChecker::VisitSlot(Slot* expr) {
212 UNREACHABLE();
213 }
214
215
216 void FastCodeGenSyntaxChecker::VisitVariableProxy(VariableProxy* expr) {
217 // Only global variable references are supported.
218 Variable* var = expr->var();
219 if (!var->is_global() || var->is_this()) BAILOUT("Non-global variable");
220
221 // Check if the global variable is existing and non-deletable.
222 if (info()->has_global_object()) {
223 LookupResult lookup;
224 info()->global_object()->Lookup(*expr->name(), &lookup);
225 if (!lookup.IsProperty()) {
226 BAILOUT("Non-existing global variable");
227 }
228 // We do not handle global variables with accessors or interceptors.
229 if (lookup.type() != NORMAL) {
230 BAILOUT("Global variable with accessors or interceptors.");
231 }
232 // We do not handle deletable global variables.
233 if (!lookup.IsDontDelete()) {
234 BAILOUT("Deletable global variable");
235 }
236 }
237 }
238
239
240 void FastCodeGenSyntaxChecker::VisitLiteral(Literal* expr) {
241 BAILOUT("Literal");
242 }
243
244
245 void FastCodeGenSyntaxChecker::VisitRegExpLiteral(RegExpLiteral* expr) {
246 BAILOUT("RegExpLiteral");
247 }
248
249
250 void FastCodeGenSyntaxChecker::VisitObjectLiteral(ObjectLiteral* expr) {
251 BAILOUT("ObjectLiteral");
252 }
253
254
255 void FastCodeGenSyntaxChecker::VisitArrayLiteral(ArrayLiteral* expr) {
256 BAILOUT("ArrayLiteral");
257 }
258
259
260 void FastCodeGenSyntaxChecker::VisitCatchExtensionObject(
261 CatchExtensionObject* expr) {
262 BAILOUT("CatchExtensionObject");
263 }
264
265
266 void FastCodeGenSyntaxChecker::VisitAssignment(Assignment* expr) {
267 // Simple assignments to (named) this properties are supported.
268 if (expr->op() != Token::ASSIGN) BAILOUT("Non-simple assignment");
269
270 Property* prop = expr->target()->AsProperty();
271 if (prop == NULL) BAILOUT("Non-property assignment");
272 VariableProxy* proxy = prop->obj()->AsVariableProxy();
273 if (proxy == NULL || !proxy->var()->is_this()) {
274 BAILOUT("Non-this-property assignment");
275 }
276 if (!prop->key()->IsPropertyName()) {
277 BAILOUT("Non-named-property assignment");
278 }
279
280 // We will only specialize for fields on the object itself.
281 // Expression::IsPropertyName implies that the name is a literal
282 // symbol but we do not assume that.
283 Literal* key = prop->key()->AsLiteral();
284 if (key != NULL && key->handle()->IsString()) {
285 Handle<Object> receiver = info()->receiver();
286 Handle<String> name = Handle<String>::cast(key->handle());
287 LookupResult lookup;
288 receiver->Lookup(*name, &lookup);
289 if (!lookup.IsProperty()) {
290 BAILOUT("Assigned property not found at compile time");
291 }
292 if (lookup.holder() != *receiver) BAILOUT("Non-own property assignment");
293 if (!lookup.type() == FIELD) BAILOUT("Non-field property assignment");
294 } else {
295 UNREACHABLE();
296 BAILOUT("Unexpected non-string-literal property key");
297 }
298
299 Visit(expr->value());
300 }
301
302
303 void FastCodeGenSyntaxChecker::VisitThrow(Throw* expr) {
304 BAILOUT("Throw");
305 }
306
307
308 void FastCodeGenSyntaxChecker::VisitProperty(Property* expr) {
309 // We support named this property references.
310 VariableProxy* proxy = expr->obj()->AsVariableProxy();
311 if (proxy == NULL || !proxy->var()->is_this()) {
312 BAILOUT("Non-this-property reference");
313 }
314 if (!expr->key()->IsPropertyName()) {
315 BAILOUT("Non-named-property reference");
316 }
317
318 // We will only specialize for fields on the object itself.
319 // Expression::IsPropertyName implies that the name is a literal
320 // symbol but we do not assume that.
321 Literal* key = expr->key()->AsLiteral();
322 if (key != NULL && key->handle()->IsString()) {
323 Handle<Object> receiver = info()->receiver();
324 Handle<String> name = Handle<String>::cast(key->handle());
325 LookupResult lookup;
326 receiver->Lookup(*name, &lookup);
327 if (!lookup.IsProperty()) {
328 BAILOUT("Referenced property not found at compile time");
329 }
330 if (lookup.holder() != *receiver) BAILOUT("Non-own property reference");
331 if (!lookup.type() == FIELD) BAILOUT("Non-field property reference");
332 } else {
333 UNREACHABLE();
334 BAILOUT("Unexpected non-string-literal property key");
335 }
336 }
337
338
339 void FastCodeGenSyntaxChecker::VisitCall(Call* expr) {
340 BAILOUT("Call");
341 }
342
343
344 void FastCodeGenSyntaxChecker::VisitCallNew(CallNew* expr) {
345 BAILOUT("CallNew");
346 }
347
348
349 void FastCodeGenSyntaxChecker::VisitCallRuntime(CallRuntime* expr) {
350 BAILOUT("CallRuntime");
351 }
352
353
354 void FastCodeGenSyntaxChecker::VisitUnaryOperation(UnaryOperation* expr) {
355 BAILOUT("UnaryOperation");
356 }
357
358
359 void FastCodeGenSyntaxChecker::VisitCountOperation(CountOperation* expr) {
360 BAILOUT("CountOperation");
361 }
362
363
364 void FastCodeGenSyntaxChecker::VisitBinaryOperation(BinaryOperation* expr) {
365 // We support bitwise OR.
366 switch (expr->op()) {
367 case Token::COMMA:
368 BAILOUT("BinaryOperation COMMA");
369 case Token::OR:
370 BAILOUT("BinaryOperation OR");
371 case Token::AND:
372 BAILOUT("BinaryOperation AND");
373
374 case Token::BIT_OR:
375 // We support expressions nested on the left because they only require
376 // a pair of registers to keep all intermediate values in registers
377 // (i.e., the expression stack has height no more than two).
378 if (!expr->right()->IsLeaf()) BAILOUT("expression nested on right");
379
380 // We do not allow subexpressions with side effects because we
381 // (currently) bail out to the beginning of the full function. The
382 // only expressions with side effects that we would otherwise handle
383 // are assignments.
384 if (expr->left()->AsAssignment() != NULL ||
385 expr->right()->AsAssignment() != NULL) {
386 BAILOUT("subexpression of binary operation has side effects");
387 }
388
389 Visit(expr->left());
390 CHECK_BAILOUT;
391 Visit(expr->right());
392 break;
393
394 case Token::BIT_XOR:
395 BAILOUT("BinaryOperation BIT_XOR");
396 case Token::BIT_AND:
397 BAILOUT("BinaryOperation BIT_AND");
398 case Token::SHL:
399 BAILOUT("BinaryOperation SHL");
400 case Token::SAR:
401 BAILOUT("BinaryOperation SAR");
402 case Token::SHR:
403 BAILOUT("BinaryOperation SHR");
404 case Token::ADD:
405 BAILOUT("BinaryOperation ADD");
406 case Token::SUB:
407 BAILOUT("BinaryOperation SUB");
408 case Token::MUL:
409 BAILOUT("BinaryOperation MUL");
410 case Token::DIV:
411 BAILOUT("BinaryOperation DIV");
412 case Token::MOD:
413 BAILOUT("BinaryOperation MOD");
414 default:
415 UNREACHABLE();
416 }
417 }
418
419
420 void FastCodeGenSyntaxChecker::VisitCompareOperation(CompareOperation* expr) {
421 BAILOUT("CompareOperation");
422 }
423
424
425 void FastCodeGenSyntaxChecker::VisitThisFunction(ThisFunction* expr) {
426 BAILOUT("ThisFunction");
427 }
428
429 #undef BAILOUT
430 #undef CHECK_BAILOUT
431
432
433 #define __ ACCESS_MASM(masm())
434
435 Handle<Code> FastCodeGenerator::MakeCode(CompilationInfo* info) {
436 // Label the AST before calling MakeCodePrologue, so AST node numbers are
437 // printed with the AST.
438 AstLabeler labeler;
439 labeler.Label(info);
440
441 CodeGenerator::MakeCodePrologue(info);
442
443 const int kInitialBufferSize = 4 * KB;
444 MacroAssembler masm(NULL, kInitialBufferSize);
445
446 // Generate the fast-path code.
447 FastCodeGenerator fast_cgen(&masm);
448 fast_cgen.Generate(info);
449 if (fast_cgen.HasStackOverflow()) {
450 ASSERT(!Top::has_pending_exception());
451 return Handle<Code>::null();
452 }
453
454 // Generate the full code for the function in bailout mode, using the same
455 // macro assembler.
456 CodeGenerator cgen(&masm);
457 CodeGeneratorScope scope(&cgen);
458 info->set_mode(CompilationInfo::SECONDARY);
459 cgen.Generate(info);
460 if (cgen.HasStackOverflow()) {
461 ASSERT(!Top::has_pending_exception());
462 return Handle<Code>::null();
463 }
464
465 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, NOT_IN_LOOP);
466 return CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
467 }
468
469
470 Register FastCodeGenerator::accumulator0() { return eax; }
471 Register FastCodeGenerator::accumulator1() { return edx; }
472 Register FastCodeGenerator::scratch0() { return ecx; }
473 Register FastCodeGenerator::scratch1() { return edi; }
474 Register FastCodeGenerator::receiver_reg() { return ebx; }
475 Register FastCodeGenerator::context_reg() { return esi; }
476
477
478 void FastCodeGenerator::EmitLoadReceiver() {
479 // Offset 2 is due to return address and saved frame pointer.
480 int index = 2 + function()->scope()->num_parameters();
481 __ mov(receiver_reg(), Operand(ebp, index * kPointerSize));
482 }
483
484
485 void FastCodeGenerator::EmitGlobalVariableLoad(Handle<Object> cell) {
486 ASSERT(!destination().is(no_reg));
487 ASSERT(cell->IsJSGlobalPropertyCell());
488
489 __ mov(destination(), Immediate(cell));
490 __ mov(destination(),
491 FieldOperand(destination(), JSGlobalPropertyCell::kValueOffset));
492 if (FLAG_debug_code) {
493 __ cmp(destination(), Factory::the_hole_value());
494 __ Check(not_equal, "DontDelete cells can't contain the hole");
495 }
496
497 // The loaded value is not known to be a smi.
498 clear_as_smi(destination());
499 }
500
501
502 void FastCodeGenerator::EmitThisPropertyStore(Handle<String> name) {
503 LookupResult lookup;
504 info()->receiver()->Lookup(*name, &lookup);
505
506 ASSERT(lookup.holder() == *info()->receiver());
507 ASSERT(lookup.type() == FIELD);
508 Handle<Map> map(Handle<HeapObject>::cast(info()->receiver())->map());
509 int index = lookup.GetFieldIndex() - map->inobject_properties();
510 int offset = index * kPointerSize;
511
512 // We will emit the write barrier unless the stored value is statically
513 // known to be a smi.
514 bool needs_write_barrier = !is_smi(accumulator0());
515
516 // Perform the store. Negative offsets are inobject properties.
517 if (offset < 0) {
518 offset += map->instance_size();
519 __ mov(FieldOperand(receiver_reg(), offset), accumulator0());
520 if (needs_write_barrier) {
521 // Preserve receiver from write barrier.
522 __ mov(scratch0(), receiver_reg());
523 }
524 } else {
525 offset += FixedArray::kHeaderSize;
526 __ mov(scratch0(),
527 FieldOperand(receiver_reg(), JSObject::kPropertiesOffset));
528 __ mov(FieldOperand(scratch0(), offset), accumulator0());
529 }
530
531 if (needs_write_barrier) {
532 if (destination().is(no_reg)) {
533 // After RecordWrite accumulator0 is only accidently a smi, but it is
534 // already marked as not known to be one.
535 __ RecordWrite(scratch0(), offset, accumulator0(), scratch1());
536 } else {
537 // Copy the value to the other accumulator to preserve a copy from the
538 // write barrier. One of the accumulators is available as a scratch
539 // register. Neither is a smi.
540 __ mov(accumulator1(), accumulator0());
541 clear_as_smi(accumulator1());
542 Register value_scratch = other_accumulator(destination());
543 __ RecordWrite(scratch0(), offset, value_scratch, scratch1());
544 }
545 } else if (destination().is(accumulator1())) {
546 __ mov(accumulator1(), accumulator0());
547 // Is a smi because we do not need the write barrier.
548 set_as_smi(accumulator1());
549 }
550 }
551
552
553 void FastCodeGenerator::EmitThisPropertyLoad(Handle<String> name) {
554 ASSERT(!destination().is(no_reg));
555 LookupResult lookup;
556 info()->receiver()->Lookup(*name, &lookup);
557
558 ASSERT(lookup.holder() == *info()->receiver());
559 ASSERT(lookup.type() == FIELD);
560 Handle<Map> map(Handle<HeapObject>::cast(info()->receiver())->map());
561 int index = lookup.GetFieldIndex() - map->inobject_properties();
562 int offset = index * kPointerSize;
563
564 // Perform the load. Negative offsets are inobject properties.
565 if (offset < 0) {
566 offset += map->instance_size();
567 __ mov(destination(), FieldOperand(receiver_reg(), offset));
568 } else {
569 offset += FixedArray::kHeaderSize;
570 __ mov(scratch0(),
571 FieldOperand(receiver_reg(), JSObject::kPropertiesOffset));
572 __ mov(destination(), FieldOperand(scratch0(), offset));
573 }
574
575 // The loaded value is not known to be a smi.
576 clear_as_smi(destination());
577 }
578
579
580 void FastCodeGenerator::EmitBitOr() {
581 if (is_smi(accumulator0()) && is_smi(accumulator1())) {
582 // If both operands are known to be a smi then there is no need to check
583 // the operands or result. There is no need to perform the operation in
584 // an effect context.
585 if (!destination().is(no_reg)) {
586 // Leave the result in the destination register. Bitwise or is
587 // commutative.
588 __ or_(destination(), Operand(other_accumulator(destination())));
589 }
590 } else {
591 // Left is in accumulator1, right in accumulator0.
592 Label* bailout = NULL;
593 if (destination().is(accumulator0())) {
594 __ mov(scratch0(), accumulator0());
595 __ or_(destination(), Operand(accumulator1())); // Or is commutative.
596 __ test(destination(), Immediate(kSmiTagMask));
597 bailout = info()->AddBailout(accumulator1(), scratch0()); // Left, right.
598 } else if (destination().is(accumulator1())) {
599 __ mov(scratch0(), accumulator1());
600 __ or_(destination(), Operand(accumulator0()));
601 __ test(destination(), Immediate(kSmiTagMask));
602 bailout = info()->AddBailout(scratch0(), accumulator0());
603 } else {
604 ASSERT(destination().is(no_reg));
605 __ mov(scratch0(), accumulator1());
606 __ or_(scratch0(), Operand(accumulator0()));
607 __ test(scratch0(), Immediate(kSmiTagMask));
608 bailout = info()->AddBailout(accumulator1(), accumulator0());
609 }
610 __ j(not_zero, bailout, not_taken);
611 }
612
613 // If we didn't bailout, the result (in fact, both inputs too) is known to
614 // be a smi.
615 set_as_smi(accumulator0());
616 set_as_smi(accumulator1());
617 }
618
619
620 void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
621 ASSERT(info_ == NULL);
622 info_ = compilation_info;
623 Comment cmnt(masm_, "[ function compiled by fast code generator");
624
625 // Save the caller's frame pointer and set up our own.
626 Comment prologue_cmnt(masm(), ";; Prologue");
627 __ push(ebp);
628 __ mov(ebp, esp);
629 __ push(esi); // Context.
630 __ push(edi); // Closure.
631 // Note that we keep a live register reference to esi (context) at this
632 // point.
633
634 Label* bailout_to_beginning = info()->AddBailout();
635 // Receiver (this) is allocated to a fixed register.
636 if (info()->has_this_properties()) {
637 Comment cmnt(masm(), ";; MapCheck(this)");
638 if (FLAG_print_ir) {
639 PrintF("#: MapCheck(this)\n");
640 }
641 ASSERT(info()->has_receiver() && info()->receiver()->IsHeapObject());
642 Handle<HeapObject> object = Handle<HeapObject>::cast(info()->receiver());
643 Handle<Map> map(object->map());
644 EmitLoadReceiver();
645 __ CheckMap(receiver_reg(), map, bailout_to_beginning, false);
646 }
647
648 // If there is a global variable access check if the global object is the
649 // same as at lazy-compilation time.
650 if (info()->has_globals()) {
651 Comment cmnt(masm(), ";; MapCheck(GLOBAL)");
652 if (FLAG_print_ir) {
653 PrintF("#: MapCheck(GLOBAL)\n");
654 }
655 ASSERT(info()->has_global_object());
656 Handle<Map> map(info()->global_object()->map());
657 __ mov(scratch0(), CodeGenerator::GlobalObject());
658 __ CheckMap(scratch0(), map, bailout_to_beginning, true);
659 }
660
661 VisitStatements(function()->body());
662
663 Comment return_cmnt(masm(), ";; Return(<undefined>)");
664 if (FLAG_print_ir) {
665 PrintF("#: Return(<undefined>)\n");
666 }
667 __ mov(eax, Factory::undefined_value());
668 __ mov(esp, ebp);
669 __ pop(ebp);
670 __ ret((scope()->num_parameters() + 1) * kPointerSize);
671 }
672
673
674 void FastCodeGenerator::VisitDeclaration(Declaration* decl) {
675 UNREACHABLE();
676 }
677
678
679 void FastCodeGenerator::VisitBlock(Block* stmt) {
680 VisitStatements(stmt->statements());
681 }
682
683
684 void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
685 Visit(stmt->expression());
686 }
687
688
689 void FastCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
690 // Nothing to do.
691 }
692
693
694 void FastCodeGenerator::VisitIfStatement(IfStatement* stmt) {
695 UNREACHABLE();
696 }
697
698
699 void FastCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
700 UNREACHABLE();
701 }
702
703
704 void FastCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
705 UNREACHABLE();
706 }
707
708
709 void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
710 UNREACHABLE();
711 }
712
713
714 void FastCodeGenerator::VisitWithEnterStatement(WithEnterStatement* stmt) {
715 UNREACHABLE();
716 }
717
718
719 void FastCodeGenerator::VisitWithExitStatement(WithExitStatement* stmt) {
720 UNREACHABLE();
721 }
722
723
724 void FastCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
725 UNREACHABLE();
726 }
727
728
729 void FastCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
730 UNREACHABLE();
731 }
732
733
734 void FastCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
735 UNREACHABLE();
736 }
737
738
739 void FastCodeGenerator::VisitForStatement(ForStatement* stmt) {
740 UNREACHABLE();
741 }
742
743
744 void FastCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
745 UNREACHABLE();
746 }
747
748
749 void FastCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
750 UNREACHABLE();
751 }
752
753
754 void FastCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
755 UNREACHABLE();
756 }
757
758
759 void FastCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
760 UNREACHABLE();
761 }
762
763
764 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
765 UNREACHABLE();
766 }
767
768
769 void FastCodeGenerator::VisitSharedFunctionInfoLiteral(
770 SharedFunctionInfoLiteral* expr) {
771 UNREACHABLE();
772 }
773
774
775 void FastCodeGenerator::VisitConditional(Conditional* expr) {
776 UNREACHABLE();
777 }
778
779
780 void FastCodeGenerator::VisitSlot(Slot* expr) {
781 UNREACHABLE();
782 }
783
784
785 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
786 ASSERT(expr->var()->is_global() && !expr->var()->is_this());
787 // Check if we can compile a global variable load directly from the cell.
788 ASSERT(info()->has_global_object());
789 LookupResult lookup;
790 info()->global_object()->Lookup(*expr->name(), &lookup);
791 // We only support normal (non-accessor/interceptor) DontDelete properties
792 // for now.
793 ASSERT(lookup.IsProperty());
794 ASSERT_EQ(NORMAL, lookup.type());
795 ASSERT(lookup.IsDontDelete());
796 Handle<Object> cell(info()->global_object()->GetPropertyCell(&lookup));
797
798 // Global variable lookups do not have side effects, so we do not need to
799 // emit code if we are in an effect context.
800 if (!destination().is(no_reg)) {
801 Comment cmnt(masm(), ";; Global");
802 if (FLAG_print_ir) {
803 SmartPointer<char> name = expr->name()->ToCString();
804 PrintF("%d: t%d = Global(%s)\n", expr->num(),
805 expr->num(), *name);
806 }
807 EmitGlobalVariableLoad(cell);
808 }
809 }
810
811
812 void FastCodeGenerator::VisitLiteral(Literal* expr) {
813 UNREACHABLE();
814 }
815
816
817 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
818 UNREACHABLE();
819 }
820
821
822 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
823 UNREACHABLE();
824 }
825
826
827 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
828 UNREACHABLE();
829 }
830
831
832 void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) {
833 UNREACHABLE();
834 }
835
836
837 void FastCodeGenerator::VisitAssignment(Assignment* expr) {
838 // Known to be a simple this property assignment. Effectively a unary
839 // operation.
840 { Register my_destination = destination();
841 set_destination(accumulator0());
842 Visit(expr->value());
843 set_destination(my_destination);
844 }
845
846 Property* prop = expr->target()->AsProperty();
847 ASSERT_NOT_NULL(prop);
848 ASSERT_NOT_NULL(prop->obj()->AsVariableProxy());
849 ASSERT(prop->obj()->AsVariableProxy()->var()->is_this());
850 ASSERT(prop->key()->IsPropertyName());
851 Handle<String> name =
852 Handle<String>::cast(prop->key()->AsLiteral()->handle());
853
854 Comment cmnt(masm(), ";; Store to this");
855 if (FLAG_print_ir) {
856 SmartPointer<char> name_string = name->ToCString();
857 PrintF("%d: ", expr->num());
858 if (!destination().is(no_reg)) PrintF("t%d = ", expr->num());
859 PrintF("Store(this, \"%s\", t%d)\n", *name_string,
860 expr->value()->num());
861 }
862
863 EmitThisPropertyStore(name);
864 }
865
866
867 void FastCodeGenerator::VisitThrow(Throw* expr) {
868 UNREACHABLE();
869 }
870
871
872 void FastCodeGenerator::VisitProperty(Property* expr) {
873 ASSERT_NOT_NULL(expr->obj()->AsVariableProxy());
874 ASSERT(expr->obj()->AsVariableProxy()->var()->is_this());
875 ASSERT(expr->key()->IsPropertyName());
876 if (!destination().is(no_reg)) {
877 Handle<String> name =
878 Handle<String>::cast(expr->key()->AsLiteral()->handle());
879
880 Comment cmnt(masm(), ";; Load from this");
881 if (FLAG_print_ir) {
882 SmartPointer<char> name_string = name->ToCString();
883 PrintF("%d: t%d = Load(this, \"%s\")\n",
884 expr->num(), expr->num(), *name_string);
885 }
886 EmitThisPropertyLoad(name);
887 }
888 }
889
890
891 void FastCodeGenerator::VisitCall(Call* expr) {
892 UNREACHABLE();
893 }
894
895
896 void FastCodeGenerator::VisitCallNew(CallNew* expr) {
897 UNREACHABLE();
898 }
899
900
901 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
902 UNREACHABLE();
903 }
904
905
906 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
907 UNREACHABLE();
908 }
909
910
911 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
912 UNREACHABLE();
913 }
914
915
916 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
917 // We support limited binary operations: bitwise OR only allowed to be
918 // nested on the left.
919 ASSERT(expr->op() == Token::BIT_OR);
920 ASSERT(expr->right()->IsLeaf());
921
922 { Register my_destination = destination();
923 set_destination(accumulator1());
924 Visit(expr->left());
925 set_destination(accumulator0());
926 Visit(expr->right());
927 set_destination(my_destination);
928 }
929
930 Comment cmnt(masm(), ";; BIT_OR");
931 if (FLAG_print_ir) {
932 PrintF("%d: ", expr->num());
933 if (!destination().is(no_reg)) PrintF("t%d = ", expr->num());
934 PrintF("BIT_OR(t%d, t%d)\n", expr->left()->num(), expr->right()->num());
935 }
936 EmitBitOr();
937 }
938
939
940 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
941 UNREACHABLE();
942 }
943
944
945 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) {
946 UNREACHABLE();
947 }
948
949 #undef __
950
951
952 } } // namespace v8::internal
953
954 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/fast-codegen-ia32.h ('k') | src/ia32/full-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698