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

Side by Side Diff: src/wasm/asm-wasm-builder.cc

Issue 1702293002: Add asm.js stdlib portion implementable as wasm opcodes. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: reflow Created 4 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
« no previous file with comments | « src/wasm/asm-wasm-builder.h ('k') | src/wasm/wasm-js.cc » ('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 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/wasm/asm-wasm-builder.h" 7 #include "src/wasm/asm-wasm-builder.h"
8 #include "src/wasm/wasm-macro-gen.h" 8 #include "src/wasm/wasm-macro-gen.h"
9 #include "src/wasm/wasm-opcodes.h" 9 #include "src/wasm/wasm-opcodes.h"
10 10
(...skipping 10 matching lines...) Expand all
21 do { \ 21 do { \
22 DCHECK(!HasStackOverflow()); \ 22 DCHECK(!HasStackOverflow()); \
23 call; \ 23 call; \
24 if (HasStackOverflow()) return; \ 24 if (HasStackOverflow()) return; \
25 } while (false) 25 } while (false)
26 26
27 27
28 class AsmWasmBuilderImpl : public AstVisitor { 28 class AsmWasmBuilderImpl : public AstVisitor {
29 public: 29 public:
30 AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal, 30 AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal,
31 Handle<Object> foreign) 31 Handle<Object> foreign, AsmTyper* typer)
32 : local_variables_(HashMap::PointersMatch, 32 : local_variables_(HashMap::PointersMatch,
33 ZoneHashMap::kDefaultHashMapCapacity, 33 ZoneHashMap::kDefaultHashMapCapacity,
34 ZoneAllocationPolicy(zone)), 34 ZoneAllocationPolicy(zone)),
35 functions_(HashMap::PointersMatch, ZoneHashMap::kDefaultHashMapCapacity, 35 functions_(HashMap::PointersMatch, ZoneHashMap::kDefaultHashMapCapacity,
36 ZoneAllocationPolicy(zone)), 36 ZoneAllocationPolicy(zone)),
37 global_variables_(HashMap::PointersMatch, 37 global_variables_(HashMap::PointersMatch,
38 ZoneHashMap::kDefaultHashMapCapacity, 38 ZoneHashMap::kDefaultHashMapCapacity,
39 ZoneAllocationPolicy(zone)), 39 ZoneAllocationPolicy(zone)),
40 in_function_(false), 40 in_function_(false),
41 is_set_op_(false), 41 is_set_op_(false),
42 marking_exported(false), 42 marking_exported(false),
43 builder_(new (zone) WasmModuleBuilder(zone)), 43 builder_(new (zone) WasmModuleBuilder(zone)),
44 current_function_builder_(nullptr), 44 current_function_builder_(nullptr),
45 literal_(literal), 45 literal_(literal),
46 isolate_(isolate), 46 isolate_(isolate),
47 zone_(zone), 47 zone_(zone),
48 foreign_(foreign), 48 foreign_(foreign),
49 typer_(typer),
49 cache_(TypeCache::Get()), 50 cache_(TypeCache::Get()),
50 breakable_blocks_(zone), 51 breakable_blocks_(zone),
51 block_size_(0), 52 block_size_(0),
52 init_function_index_(0), 53 init_function_index_(0),
53 next_table_index_(0), 54 next_table_index_(0),
54 function_tables_(HashMap::PointersMatch, 55 function_tables_(HashMap::PointersMatch,
55 ZoneHashMap::kDefaultHashMapCapacity, 56 ZoneHashMap::kDefaultHashMapCapacity,
56 ZoneAllocationPolicy(zone)), 57 ZoneAllocationPolicy(zone)),
57 imported_function_table_(this) { 58 imported_function_table_(this) {
58 InitializeAstVisitor(isolate); 59 InitializeAstVisitor(isolate);
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 } 365 }
365 366
366 void VisitConditional(Conditional* expr) { 367 void VisitConditional(Conditional* expr) {
367 DCHECK(in_function_); 368 DCHECK(in_function_);
368 current_function_builder_->Emit(kExprIfElse); 369 current_function_builder_->Emit(kExprIfElse);
369 RECURSE(Visit(expr->condition())); 370 RECURSE(Visit(expr->condition()));
370 RECURSE(Visit(expr->then_expression())); 371 RECURSE(Visit(expr->then_expression()));
371 RECURSE(Visit(expr->else_expression())); 372 RECURSE(Visit(expr->else_expression()));
372 } 373 }
373 374
375 bool VisitStdlibConstant(Variable* var) {
376 AsmTyper::StandardMember standard_object =
377 typer_->VariableAsStandardMember(var);
378 switch (standard_object) {
379 case AsmTyper::kInfinity: {
380 double infinity = std::numeric_limits<double>::infinity();
381 byte code[] = {WASM_F64(infinity)};
382 current_function_builder_->EmitCode(code, sizeof(code));
383 return true;
384 }
385 case AsmTyper::kNaN: {
386 double nan = std::numeric_limits<double>::signaling_NaN();
387 byte code[] = {WASM_F64(nan)};
388 current_function_builder_->EmitCode(code, sizeof(code));
389 return true;
390 }
391 case AsmTyper::kMathE: {
392 byte code[] = {WASM_F64(M_E)};
393 current_function_builder_->EmitCode(code, sizeof(code));
394 return true;
395 }
396 case AsmTyper::kMathLN10: {
397 byte code[] = {WASM_F64(M_LN10)};
398 current_function_builder_->EmitCode(code, sizeof(code));
399 return true;
400 }
401 case AsmTyper::kMathLN2: {
402 byte code[] = {WASM_F64(M_LN2)};
403 current_function_builder_->EmitCode(code, sizeof(code));
404 return true;
405 }
406 case AsmTyper::kMathLOG10E: {
407 byte code[] = {WASM_F64(M_LOG10E)};
408 current_function_builder_->EmitCode(code, sizeof(code));
409 return true;
410 }
411 case AsmTyper::kMathLOG2E: {
412 byte code[] = {WASM_F64(M_LOG2E)};
413 current_function_builder_->EmitCode(code, sizeof(code));
414 return true;
415 }
416 case AsmTyper::kMathPI: {
417 byte code[] = {WASM_F64(M_PI)};
418 current_function_builder_->EmitCode(code, sizeof(code));
419 return true;
420 }
421 case AsmTyper::kMathSQRT1_2: {
422 byte code[] = {WASM_F64(M_SQRT1_2)};
423 current_function_builder_->EmitCode(code, sizeof(code));
424 return true;
425 }
426 case AsmTyper::kMathSQRT2: {
427 byte code[] = {WASM_F64(M_SQRT2)};
428 current_function_builder_->EmitCode(code, sizeof(code));
429 return true;
430 }
431 default: { break; }
432 }
433 return false;
434 }
435
374 void VisitVariableProxy(VariableProxy* expr) { 436 void VisitVariableProxy(VariableProxy* expr) {
375 if (in_function_) { 437 if (in_function_) {
376 Variable* var = expr->var(); 438 Variable* var = expr->var();
377 if (is_set_op_) { 439 if (is_set_op_) {
378 if (var->IsContextSlot()) { 440 if (var->IsContextSlot()) {
379 current_function_builder_->Emit(kExprStoreGlobal); 441 current_function_builder_->Emit(kExprStoreGlobal);
380 } else { 442 } else {
381 current_function_builder_->Emit(kExprSetLocal); 443 current_function_builder_->Emit(kExprSetLocal);
382 } 444 }
383 is_set_op_ = false; 445 is_set_op_ = false;
384 } else { 446 } else {
447 if (VisitStdlibConstant(var)) {
448 return;
aseemgarg 2016/02/17 19:44:06 get rid of the return and instead make the conditi
bradn 2016/02/19 07:16:52 But I'm returning because I don't actually want to
449 }
385 if (var->IsContextSlot()) { 450 if (var->IsContextSlot()) {
386 current_function_builder_->Emit(kExprLoadGlobal); 451 current_function_builder_->Emit(kExprLoadGlobal);
387 } else { 452 } else {
388 current_function_builder_->Emit(kExprGetLocal); 453 current_function_builder_->Emit(kExprGetLocal);
389 } 454 }
390 } 455 }
391 LocalType var_type = TypeOf(expr); 456 LocalType var_type = TypeOf(expr);
392 DCHECK_NE(kAstStmt, var_type); 457 DCHECK_NE(kAstStmt, var_type);
393 if (var->IsContextSlot()) { 458 if (var->IsContextSlot()) {
394 AddLeb128(LookupOrInsertGlobal(var, var_type), false); 459 AddLeb128(LookupOrInsertGlobal(var, var_type), false);
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 DCHECK(binop->right()->IsLiteral()); 647 DCHECK(binop->right()->IsLiteral());
583 DCHECK_EQ(0.0, binop->right()->AsLiteral()->raw_value()->AsNumber()); 648 DCHECK_EQ(0.0, binop->right()->AsLiteral()->raw_value()->AsNumber());
584 DCHECK(!binop->right()->AsLiteral()->raw_value()->ContainsDot()); 649 DCHECK(!binop->right()->AsLiteral()->raw_value()->ContainsDot());
585 VisitForeignVariable(false, prop); 650 VisitForeignVariable(false, prop);
586 } else { 651 } else {
587 UNREACHABLE(); 652 UNREACHABLE();
588 } 653 }
589 UnLoadInitFunction(); 654 UnLoadInitFunction();
590 return; 655 return;
591 } 656 }
657 Property* prop = expr->value()->AsProperty();
658 if (prop != nullptr) {
659 if (TypeOf(expr->value()) != kAstStmt) {
660 // Assume it's part of stdlib.
661 return;
662 }
663 }
592 // TODO(bradnelson): Get rid of this. 664 // TODO(bradnelson): Get rid of this.
593 if (TypeOf(expr->value()) == kAstStmt) { 665 if (TypeOf(expr->value()) == kAstStmt) {
594 Property* prop = expr->value()->AsProperty(); 666 Property* prop = expr->value()->AsProperty();
595 if (prop != nullptr) { 667 if (prop != nullptr) {
596 VariableProxy* vp = prop->obj()->AsVariableProxy(); 668 VariableProxy* vp = prop->obj()->AsVariableProxy();
597 if (vp != nullptr && vp->var()->IsParameter() && 669 if (vp != nullptr && vp->var()->IsParameter()) {
aseemgarg 2016/02/17 19:44:06 what's the change here?
bradn 2016/02/19 07:16:52 Oops, dropped.
598 vp->var()->index() == 1) { 670 fprintf(stderr, "%d\n", vp->var()->index());
aseemgarg 2016/02/17 19:44:06 get rid of fprintf
bradn 2016/02/19 07:16:52 Done.
599 VariableProxy* target = expr->target()->AsVariableProxy(); 671 if (vp->var()->index() == 1) {
600 if (target->bounds().lower->Is(Type::Function())) { 672 VariableProxy* target = expr->target()->AsVariableProxy();
601 const AstRawString* name = 673 if (target->bounds().lower->Is(Type::Function())) {
602 prop->key()->AsLiteral()->AsRawPropertyName(); 674 const AstRawString* name =
603 imported_function_table_.AddImport( 675 prop->key()->AsLiteral()->AsRawPropertyName();
604 target->var(), name->raw_data(), name->length()); 676 imported_function_table_.AddImport(
677 target->var(), name->raw_data(), name->length());
678 }
605 } 679 }
606 } 680 }
607 } 681 }
608 ArrayLiteral* funcs = expr->value()->AsArrayLiteral(); 682 ArrayLiteral* funcs = expr->value()->AsArrayLiteral();
609 if (funcs != nullptr && 683 if (funcs != nullptr &&
610 funcs->bounds().lower->AsArray()->Element()->IsFunction()) { 684 funcs->bounds().lower->AsArray()->Element()->IsFunction()) {
611 VariableProxy* target = expr->target()->AsVariableProxy(); 685 VariableProxy* target = expr->target()->AsVariableProxy();
612 DCHECK_NOT_NULL(target); 686 DCHECK_NOT_NULL(target);
613 AddFunctionTable(target, funcs); 687 AddFunctionTable(target, funcs);
614 } 688 }
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
758 current_function_builder_->Emit(kExprI32And); 832 current_function_builder_->Emit(kExprI32And);
759 byte code[] = {WASM_I8(~(size - 1))}; 833 byte code[] = {WASM_I8(~(size - 1))};
760 current_function_builder_->EmitCode(code, sizeof(code)); 834 current_function_builder_->EmitCode(code, sizeof(code));
761 RECURSE(Visit(binop->left())); 835 RECURSE(Visit(binop->left()));
762 return; 836 return;
763 } 837 }
764 } 838 }
765 UNREACHABLE(); 839 UNREACHABLE();
766 } 840 }
767 841
842 bool VisitStdlibFunction(Call* call, VariableProxy* expr) {
843 Variable* var = expr->var();
844 AsmTyper::StandardMember standard_object =
845 typer_->VariableAsStandardMember(var);
846 ZoneList<Expression*>* args = call->arguments();
847 LocalType call_type = TypeOf(call);
848 switch (standard_object) {
849 case AsmTyper::kNone: {
850 return false;
851 }
852 case AsmTyper::kMathAcos: {
853 UNREACHABLE();
854 break; // TODO(bradnelson): Implement as external.
855 }
856 case AsmTyper::kMathAsin: {
857 UNREACHABLE();
858 break; // TODO(bradnelson): Implement as external.
859 }
860 case AsmTyper::kMathAtan: {
861 UNREACHABLE();
862 break; // TODO(bradnelson): Implement as external.
863 }
864 case AsmTyper::kMathCos: {
865 UNREACHABLE();
866 break; // TODO(bradnelson): Implement as external.
867 }
868 case AsmTyper::kMathSin: {
869 UNREACHABLE();
870 break; // TODO(bradnelson): Implement as external.
871 }
872 case AsmTyper::kMathTan: {
873 UNREACHABLE();
874 break; // TODO(bradnelson): Implement as external.
875 }
876 case AsmTyper::kMathExp: {
877 UNREACHABLE();
878 break; // TODO(bradnelson): Implement as external.
879 }
880 case AsmTyper::kMathLog: {
881 UNREACHABLE();
882 break; // TODO(bradnelson): Implement as external.
883 }
884 case AsmTyper::kMathCeil: {
885 if (call_type == kAstF32) {
886 current_function_builder_->Emit(kExprF32Ceil);
887 } else if (call_type == kAstF64) {
888 current_function_builder_->Emit(kExprF64Ceil);
889 } else {
890 UNREACHABLE();
891 }
892 break;
893 }
894 case AsmTyper::kMathFloor: {
895 if (call_type == kAstF32) {
896 current_function_builder_->Emit(kExprF32Floor);
897 } else if (call_type == kAstF64) {
898 current_function_builder_->Emit(kExprF64Floor);
899 } else {
900 UNREACHABLE();
901 }
902 break;
903 }
904 case AsmTyper::kMathSqrt: {
905 if (call_type == kAstF32) {
906 current_function_builder_->Emit(kExprF32Sqrt);
907 } else if (call_type == kAstF64) {
908 current_function_builder_->Emit(kExprF64Sqrt);
909 } else {
910 UNREACHABLE();
911 }
912 break;
913 }
914 case AsmTyper::kMathAbs: {
915 // TODO(bradnelson): Handle signed.
916 if (call_type == kAstF32) {
917 current_function_builder_->Emit(kExprF32Abs);
918 } else if (call_type == kAstF64) {
919 current_function_builder_->Emit(kExprF64Abs);
920 } else {
921 UNREACHABLE();
922 }
923 break;
924 }
925 case AsmTyper::kMathMin: {
926 // TODO(bradnelson): Handle signed.
927 if (call_type == kAstF32) {
928 current_function_builder_->Emit(kExprF32Min);
titzer 2016/02/17 09:49:33 Can you double check that the JS min/max correspon
bradn 2016/02/19 07:16:53 Yes there is a difference around NaNs I intend to
929 } else if (call_type == kAstF64) {
930 current_function_builder_->Emit(kExprF64Min);
931 } else {
932 UNREACHABLE();
933 }
934 break;
935 }
936 case AsmTyper::kMathMax: {
937 // TODO(bradnelson): Handle signed.
938 if (call_type == kAstF32) {
939 current_function_builder_->Emit(kExprF32Max);
940 } else if (call_type == kAstF64) {
941 current_function_builder_->Emit(kExprF64Max);
942 } else {
943 UNREACHABLE();
944 }
945 break;
946 }
947 case AsmTyper::kMathAtan2: {
948 UNREACHABLE();
949 break; // TODO(bradnelson): Implement as external.
950 }
951 case AsmTyper::kMathPow: {
952 UNREACHABLE();
953 break; // TODO(bradnelson): Implement as external.
954 }
955 case AsmTyper::kMathImul: {
titzer 2016/02/17 09:49:33 Should be a simple kExprI32Mul.
bradn 2016/02/19 07:16:53 Done.
956 UNREACHABLE();
957 break; // TODO(bradnelson): Implement this inline.
958 }
959 case AsmTyper::kMathFround: {
960 DCHECK(args->length() == 1);
961 Literal* literal = args->at(0)->AsLiteral();
962 if (literal != NULL) {
963 if (literal->raw_value()->IsNumber()) {
964 float val = static_cast<float>(literal->raw_value()->AsNumber());
965 byte code[] = {WASM_F32(val)};
966 current_function_builder_->EmitCode(code, sizeof(code));
967 return true;
968 }
969 }
970 break;
971 }
972 default: { break; }
973 }
974 // Visit arguments.
975 for (int i = 0; i < args->length(); ++i) {
976 Expression* arg = args->at(i);
977 Visit(arg);
978 }
979 return true;
980 }
981
768 void VisitCall(Call* expr) { 982 void VisitCall(Call* expr) {
769 Call::CallType call_type = expr->GetCallType(isolate_); 983 Call::CallType call_type = expr->GetCallType(isolate_);
770 switch (call_type) { 984 switch (call_type) {
771 case Call::OTHER_CALL: { 985 case Call::OTHER_CALL: {
772 DCHECK(in_function_); 986 DCHECK(in_function_);
987 VariableProxy* proxy = expr->expression()->AsVariableProxy();
988 if (proxy != NULL) {
989 if (VisitStdlibFunction(expr, proxy)) {
990 return;
991 }
992 }
773 uint16_t index; 993 uint16_t index;
774 VariableProxy* vp = expr->expression()->AsVariableProxy(); 994 VariableProxy* vp = expr->expression()->AsVariableProxy();
775 if (vp != nullptr && 995 if (vp != nullptr &&
776 Type::Any()->Is(vp->bounds().lower->AsFunction()->Result())) { 996 Type::Any()->Is(vp->bounds().lower->AsFunction()->Result())) {
777 LocalType return_type = TypeOf(expr); 997 LocalType return_type = TypeOf(expr);
778 ZoneList<Expression*>* args = expr->arguments(); 998 ZoneList<Expression*>* args = expr->arguments();
779 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, 999 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1,
780 args->length()); 1000 args->length());
781 if (return_type != kAstStmt) { 1001 if (return_type != kAstStmt) {
782 sig.AddReturn(return_type); 1002 sig.AddReturn(return_type);
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after
1259 ZoneHashMap global_variables_; 1479 ZoneHashMap global_variables_;
1260 bool in_function_; 1480 bool in_function_;
1261 bool is_set_op_; 1481 bool is_set_op_;
1262 bool marking_exported; 1482 bool marking_exported;
1263 WasmModuleBuilder* builder_; 1483 WasmModuleBuilder* builder_;
1264 WasmFunctionBuilder* current_function_builder_; 1484 WasmFunctionBuilder* current_function_builder_;
1265 FunctionLiteral* literal_; 1485 FunctionLiteral* literal_;
1266 Isolate* isolate_; 1486 Isolate* isolate_;
1267 Zone* zone_; 1487 Zone* zone_;
1268 Handle<Object> foreign_; 1488 Handle<Object> foreign_;
1489 AsmTyper* typer_;
1269 TypeCache const& cache_; 1490 TypeCache const& cache_;
1270 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; 1491 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_;
1271 int block_size_; 1492 int block_size_;
1272 uint16_t init_function_index_; 1493 uint16_t init_function_index_;
1273 uint32_t next_table_index_; 1494 uint32_t next_table_index_;
1274 ZoneHashMap function_tables_; 1495 ZoneHashMap function_tables_;
1275 ImportedFunctionTable imported_function_table_; 1496 ImportedFunctionTable imported_function_table_;
1276 1497
1277 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); 1498 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
1278 1499
1279 private: 1500 private:
1280 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); 1501 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl);
1281 }; 1502 };
1282 1503
1283 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone, 1504 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone,
1284 FunctionLiteral* literal, Handle<Object> foreign) 1505 FunctionLiteral* literal, Handle<Object> foreign,
1285 : isolate_(isolate), zone_(zone), literal_(literal), foreign_(foreign) {} 1506 AsmTyper* typer)
1507 : isolate_(isolate),
1508 zone_(zone),
1509 literal_(literal),
1510 foreign_(foreign),
1511 typer_(typer) {}
1286 1512
1287 // TODO(aseemgarg): probably should take zone (to write wasm to) as input so 1513 // TODO(aseemgarg): probably should take zone (to write wasm to) as input so
1288 // that zone in constructor may be thrown away once wasm module is written. 1514 // that zone in constructor may be thrown away once wasm module is written.
1289 WasmModuleIndex* AsmWasmBuilder::Run() { 1515 WasmModuleIndex* AsmWasmBuilder::Run() {
1290 AsmWasmBuilderImpl impl(isolate_, zone_, literal_, foreign_); 1516 AsmWasmBuilderImpl impl(isolate_, zone_, literal_, foreign_, typer_);
1291 impl.Compile(); 1517 impl.Compile();
1292 WasmModuleWriter* writer = impl.builder_->Build(zone_); 1518 WasmModuleWriter* writer = impl.builder_->Build(zone_);
1293 return writer->WriteTo(zone_); 1519 return writer->WriteTo(zone_);
1294 } 1520 }
1295 } // namespace wasm 1521 } // namespace wasm
1296 } // namespace internal 1522 } // namespace internal
1297 } // namespace v8 1523 } // namespace v8
OLDNEW
« no previous file with comments | « src/wasm/asm-wasm-builder.h ('k') | src/wasm/wasm-js.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698